2010-08-10 5 views
4

J'ai une application Qt avec un script/jit intégré. Maintenant, j'aimerais recevoir la sortie du script sur un QTextEdit (plus spécifique QPlainTextEdit). À cette fin, des rappels sont émis. Le problème auquel je suis confronté est que quoi que j'essaie, la sortie vers TextEdit est soit retardée jusqu'à ce que le script soit terminé, soit bloquée après 2-3 secondes (et est retardée jusqu'à ce que le script soit terminé). J'ai essayé d'utiliser des signaux et des emplacements pour la mise à jour, mais aussi des appels de fonction directs - ni travaillé. Le fait de repeindre/mettre à jour le TextEdit et le formulaire parent ainsi que QCoreApplication :: flush() a également montré peu/pas d'effet. On dirait que je fais quelque chose de fondamentalement faux. Des idées ou des exemples comment réaliser les mises à jour "en temps réel"? Btw, les routines de mise à jour sont appelées - la sortie de débogage vers stdout est disponible en temps réel."temps réel" mise à jour d'un Qt TextView

+0

Quel thread exécute les rappels? Plus précisément, dans quel thread mettez-vous à jour votre QTextEdit? –

+0

Ce n'est pas thread - ce qui pourrait être une partie du problème. Donc tout (pour autant que je comprends) se passe dans le fil principal. J'ai essayé d'utiliser des threads, mais démarrer le JIT mono dans un QThread provoque un crash lié au GC (qui aime aussi lancer des pthreads) - au moins sur Mac (sur Windows je n'ai pas de vraie sortie de débogage car mon gdb est muet pour certaines raisons). – FFox

+2

Eh bien c'est probablement pourquoi vos mises à jour ne sont pas visibles en temps réel. Vous pouvez essayer d'appeler QCoreApplication :: processEvents. Mais la vraie solution serait d'exécuter tout ce que vous faites dans un thread séparé et d'utiliser des slots/signaux pour mettre à jour votre interface graphique (en remplaçant vos callbacks). –

Répondre

1

Juste pour esquisser un soluting utilisant des fils, que j'ai utilisé plusieurs fois à des fins d'exploitation forestière et qui fonctionne comme vous le souhaitez:

Définir votre classe de fil:

class MyThread : public QThread 
{ 
    Q_OBJECT 
public: 
    MyThread(QObject *parent=0) : QThread(parent) {} 
signals: 
    void signalLogMessage(const QString &logMessage); 

... 
}; 

Chaque fois que vous voulez un message de journal à être montré dans le thread principal, il suffit d'utiliser

emit signalLogMessage("Foo!");

dans votre thread principal:

MyThread *thread = new MyThread(this); 
connect(thread, SIGNAL(signalLogMessage(const QString&)), 
     this, SLOT(logMessageFromThread(const QString&))); 
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
... 
thread->start(); 

logMessageFromThread fait quelque chose comme myPlainTextEdit->appendPlainText(message). Cela fonctionne sans aucun retard ou d'autres problèmes.

J'espère que cela aide.

1

Permettez-moi de répondre moi-même à la question (en parties). Tout d'abord, il faut comprendre que Qt lui-même est construit autour de son propre concept de signal et de slot. Par conséquent, on ne peut pas s'attendre à une mise à jour en temps réel d'un QTextView puisque l'ajout de texte (que ce soit par un curseur de texte ou un ajout simple) ne fait que déclencher un signal. Donc, quoi que vous fassiez quand vous n'avez qu'un seul thread, tout ce que vous faites est de déclencher les signaux pour la mise à jour de vos widgets. Les emplacements correspondants seront traités avec une priorité beaucoup plus faible et donc après la fin de la routine de travail de blocage. Tout ceci peut être allégé en appelant QCoreApplication :: processEvents() comme indiqué dans les commentaires par Idan K. Ceci impose le traitement séquentiel de tous les événements non traités et revient ensuite. En utilisant cette fonction, QTextEdit peut être utilisé comme une console de sortie "en temps réel". Toutefois, comme indiqué par Idan et Greg, la meilleure solution utilise un thread de travail distinct, émettant des signaux dans le thread graphique. Comme ce sont des threads séparés, l'interface graphique peut traiter les slots correspondants pendant que le worker continue à fonctionner. Donc la sortie en théorie pourrait être un peu retardée par rapport à. à la solution ci-dessus, mais l'application entière restera sensible.

Aussi je tiens à ajouter que mes problèmes en utilisant QThread avec mono ont été résolus en créant le domaine global de l'application en dehors de la boucle et en utilisant mono_thread_attach() comme suggéré here. Il fonctionne bien sur Mac OS X et Windows 7.

+0

Merci pour l'explication. – darkgaze

Questions connexes