2009-10-02 5 views
3

Je suis en train de développer une application dans laquelle je veux recevoir en continu des images de l'hôte distant et les afficher sur mon écran. pour cela, je suis la stratégie donnée 1) J'ai un objet principal QWidget qui contient le QImage dessus (fonctionne bien) 2) Les images reçues de l'hôte distant sont peintes sur l'objet QImage, ce travail est fait dans un thread de travail en utilisant QPainter. (fonctionne bien) 3) mais le problème est que l'image n'est pas mise à jour sur QWidget, sauf si je redimensionne le widget, parce que l'événement repaint est appelé pour QWidget ... Maintenant, si je repeins le QWidget du thread "QPixmap: Il est dangereux d'utiliser des pixmaps en dehors du thread graphique" .. et des plantages d'application.Problème de peinture sur le thread graphique hors ligne de QWidget

Toute aide à ce sujet?

Répondre

9

émettent un signal provenant du thread de travail avec un QueuedConnection
ou soumettre un événement de mise à jour (QPaintEvent) pour le widget dans le thread de travail.

//--------------Send Queued signal--------------------- 
class WorkerThread : public QThread 
{ 
    //... 
signals: 
    void updateImage(); 

protected: 
    void run() 
    { 
     // construct QImage 
     //... 
     emit updateImage(); 
    } 
    //... 
}; 

//... 
widgetThatPaintsImage->connect(
    workerThread, 
    SIGNAL(updateImage()), 
    SLOT(update()), 
    Qt::QueuedConnection); 
//... 

//--------------postEvent Example----------------------- 
class WorkerThread : public QThread 
{ 
    //... 
protected: 
    void run() 
    { 
     //construct image 
     if(widgetThatPaintsImage) 
     { 
      QCoreApplication::postEvent(
       widgetThatPaintsImage, 
       new QPaintEvent(widgetThatPaintsImage->rect())); 
     } 
     //... 
    } 

private: 
    QPointer<QWidget> widgetThatPaintsImage; 
}; 

N'oubliez pas de synchroniser l'accès à l'image. En alternative à la synchronisation, vous pouvez également envoyer l'image au thread graphique, comme dans le Mandelbrot Example

+0

pouvez-vous s'il vous plaît envoyez-moi un extrait de code qui peut aider. –

1

Les opérations GUI en dehors du thread principal ne sont pas autorisées dans Qt. Toutes les opérations de l'interface graphique doivent être effectuées dans le thread principal, le thread où réside QApplication. Toute opération GUI dans un autre thread donne des résultats imprévisibles, c'est-à-dire des plantages.

1

Il y a un gros problème avec qt si vous souhaitez développer des plugins. Si l'application hôte est une application non-qt (beaucoup de programmes ...), et que vous voulez ajouter 2 ou 3 plugin GUI, vous avez de gros problèmes (comme je le suis).

Le problème est que, il doit y avoir juste 1 QApplication dans un processus. (Généralement dans le principal) Si vous écrivez un plugin, vous ne pouvez pas vous permettre de verrouiller l'application hôte avec un QApplication.exec().

Dans ce cas, vous pouvez créer un QThread avec QApplication et exec dans la fonction run(). Cela fonctionnera correctement. Mais celui-ci ne peut pas résoudre le problème original. Votre deuxième plugin n'a pas de QApplication ... car le processus hôte en a un. (donner le pointeur de Qapplication dans une mémoire partagée n'est pas une option ... parce que QWidget doit créer sur le fil GUI ... il y en a toujours un ...)

Et pour votre question voici la réponse. Si vous voulez créer un seul plugin, vous pouvez utiliser QMetaObject :: invokeMethod ce code définit une pixmap à une étiquette et met à jour gui.

QImage img;... bool succ = QMetaObject::invokeMethod(mainWin, "DisplaySlot", Qt::QueuedConnection, Q_ARG(QImage, img));

et ajouter un emplacement public: à votre fenêtre Displayer

void mainWinClass::DisplaySlot(QImage qim) { (*(ui.label)).setPixmap(QPixmap::fromImage(qim)); (*(ui.label)).update(); }

J'espère que ça aide.

Si quelqu'un connaît une solution à mon problème ... décrit ci-dessus (plugin gui multiple avec qt dans une application hôte) s'il vous plaît écrivez-moi.

Questions connexes