web-dev-qa-db-fra.com

Repeindre / Redessiner / Mettre à jour / Faire quelque chose

Je suis nouveau sur QT. Je comprends que vous pouvez forcer un rafraîchissement de l'affichage, mais j'ai tiré tous mes cheveux en essayant de comprendre comment. Voici ce que j'essaie spécifiquement de faire.

J'appuie sur un bouton (événement de signal onClick), qui exécute du code qui change une image (QLabel) sur l'écran, attend la saisie, puis procède en changeant une nouvelle image (QLabel différent). J'ai tout essayé et l'affichage ne se rafraîchit que lorsque le code d'événement du signal onclick est terminé. Pour le moment, je n'attends pas la saisie de l'utilisateur, j'utilise l'usep (~ 500 ms) à des fins de test.

D'après ce que j'ai lu, QT est axé sur les événements, ce qui signifie que je crée essentiellement un tas d'événements, qui sont mis dans un que et exécutés lorsque (l'événement de signal onClick) revient dans la (boucle principale)/(gestionnaire d'événements). Je ne veux pas attendre que la fonction soit terminée, cela va rendre la programmation extrêmement pénible si je dois accomplir cette routine entièrement basée sur les événements.

Comment puis-je forcer le pixmap QLabel à se rafraîchir. J'ai tout essayé. Voici tout le code que j'ai essayé dans mon gestionnaire d'événements de signal onClick. (upButton est le nom du QLabel qui est un pixmap)

update();
repaint();
ui->upButton->setUpdatesEnabled(TRUE);
update();
repaint();
QPaintEvent paintevent(ui->upButton->childrenRegion());
QPaintEvent * test = &paintevent;
paintEvent(test);
this->changeEvent(test);
ui->upButton->update();
ui->upButton->repaint();
ui->upButton->repaint(ui->upButton->childrenRegion());
repaint();
QApplication::sendPostedEvents();
this->parentWidget()->update();
usleep(100000);

Comme vous pouvez le voir, je tire juste dans le noir à ce stade. J'ai essayé de regarder un exemple de code et de faire tous mes devoirs, mais je suis perdu. Appréciez toute aide, conseil et/ou exemple de code.

23
Jason Kotzin

J'utilisais le sommeil pour émuler un court laps de temps pendant lequel l'ordinateur attendait que quelque chose se produise.

Comme je l'ai dit dans ma question, je ne voulais pas utiliser les événements parce que c'est beaucoup de travail inutile pour accomplir quelque chose extrêmement simplement.

De plus, "l'événement" qui doit avoir lieu pour que le programme continue, est un événement USB. Étant donné que j'utilise un périphérique de classe HID, il n'y a aucun moyen de définir un événement qui se produise sans boucle d'attente. Les classes USB HID ne permettent pas de définir des interruptions, le système d'exploitation revendique l'appareil.

J'ai réussi à faire fonctionner ce qui précède. J'ai parcouru le débogueur et j'ai remarqué que l'affichage se rafraîchirait avant la fonction de veille. En exécutant le programme indépendamment, j'ai obtenu des résultats aléatoires avec l'affichage rafraîchissant 1% du temps. Je me suis débarrassé de la fonction sommeil et j'ai ajouté un autre code à sa place pour émuler un retard, et ça allait.

Juste pour la connaissance de tout le monde, c'est possible, ce n'est pas interdit, et c'est facile à faire avec ce qui suit:

qApp->processEvents();

qApp est une variable externe globale dans l'en-tête QApplication.

Parce que cet événement USB rend mon flux délicat, je suis tombé sur la classe QWaitCondition. J'allais lancer un processus en attendant l'événement USB. J'attendrais que le processus libère la condition d'attente pour que ma routine se poursuive.

Mais si quelqu'un pense que c'est une mauvaise idée, s'il vous plaît, parlez. J'apprécie vraiment vos commentaires PiedPiper et Hostile Fork.

Je vous remercie.

24
Jason Kotzin

Vous ne devez pas attendre la saisie de votre gestionnaire d'événements. Vous devez repenser la logique de votre programme pour utiliser les événements comme ils étaient destinés. Tous les appels update () et repaint () dans votre code ne sont pas nécessaires si vous revenez à la boucle d'événements.

7
PiedPiper

J'ai remarqué parfois que lorsque vous avez plusieurs widgets en couches, ou des widgets à l'intérieur des widgets, cela aide à appeler leurs événements repaint ().

Par exemple

this->repaint();
this->parentWidget()->repaint();
this->parentWidget()->parentWidget()->repaint();

C'est beaucoup plus facile que de pousser n'importe quel traitement vers un autre thread ou de créer des gestionnaires d'événements supplémentaires.

7
Goddard

Si j'ai bien compris, vous avez une fente et dans cette fente, vous mettez à jour l'image montrée dans un QLabel. Mais vous voulez que cette modification soit affichée avant la fin du slot.

Si tel est le cas, émettez un événement update () et appelez qApp-> processEvents (). Cette méthode traite les événements qui sont en attente dans la file d'attente des événements, puis revient, c'est donc peut-être ce que vous recherchez.

PS: une mise à jour () peut ne pas être nécessaire du tout, je ne suis pas sûr.

2
erelender