Type personnalisé en file d'attente
L'exemple de type personnalisé en file d'attente montre comment envoyer des types personnalisés entre des threads avec des signaux et des slots en file d'attente.

Vue d'ensemble
Dans cet exemple, nous créons une classe de valeur, Block, et l'enregistrons auprès du système de méta-objets afin de pouvoir envoyer des instances de ce type entre les threads à l'aide de signaux et de créneaux mis en file d'attente.
La classe de bloc
La classe Block fournit un constructeur par défaut, un constructeur de copie et un destructeur dans la section publique de la classe, comme l'exige le système de méta-objets. La classe décrit un rectangle coloré.
class Block { public: Block(); Block(const Block &other); ~Block(); Block(const QRect &rect, const QColor &color); QColor color() const; QRect rect() const; private: QRect m_rect; QColor m_color; }; Q_DECLARE_METATYPE(Block);
Nous devrons toujours l'enregistrer auprès du système de méta-objets au moment de l'exécution en appelant la fonction modèle qRegisterMetaType() avant d'effectuer des connexions de fentes de signaux qui utilisent ce type. Même si nous n'avons pas l'intention d'utiliser le type avec QVariant dans cet exemple, c'est une bonne pratique de déclarer également le nouveau type avec Q_DECLARE_METATYPE().
L'implémentation de la classe Block est triviale, c'est pourquoi nous évitons de la citer ici.
La classe Window
Nous définissons une classe Window simple avec un slot public qui accepte un objet Block. Le reste de la classe s'occupe de la gestion de l'interface utilisateur et des images.
class Window : public QWidget { Q_OBJECT public: Window(QWidget *parent = nullptr); void loadImage(const QImage &image); public slots: void addBlock(const Block &block); private slots: void loadImage(); void resetUi(); private: QLabel *label; QPixmap pixmap; QPushButton *loadButton; QPushButton *resetButton; QString path; RenderThread *thread; };
La classe Window contient également un thread de travail, fourni par un objet RenderThread. Celui-ci émettra des signaux pour envoyer des objets Block à l'emplacement addBlock(Block) de la fenêtre.
Les parties de la classe Window les plus pertinentes sont le constructeur et l'emplacement addBlock(Block).
Le constructeur crée un thread pour le rendu des images, met en place une interface utilisateur contenant une étiquette et deux boutons poussoirs connectés à des slots de la même classe.
Window::Window(QWidget *parent) : QWidget(parent), thread(new RenderThread(this)) { label = new QLabel(this); label->setAlignment(Qt::AlignCenter); loadButton = new QPushButton(tr("&Load image..."), this); resetButton = new QPushButton(tr("&Stop"), this); resetButton->setEnabled(false); connect(loadButton, &QPushButton::clicked, this, QOverload<>::of(&Window::loadImage)); connect(resetButton, &QPushButton::clicked, thread, &RenderThread::requestInterruption); connect(thread, &RenderThread::finished, this, &Window::resetUi); connect(thread, &RenderThread::sendBlock, this, &Window::addBlock);
Dans la dernière de ces connexions, nous connectons un signal dans l'objet RenderThread à l'emplacement addBlock(Block) dans la fenêtre.
...
setWindowTitle(tr("Queued Custom Type"));
}Le reste du constructeur définit simplement la disposition de la fenêtre.
L'emplacement addBlock(Block) reçoit des blocs du fil de rendu via la connexion signal-emplacement établie dans le constructeur :
void Window::addBlock(const Block &block) { QColor color = block.color(); color.setAlpha(64); QPainter painter; painter.begin(&pixmap); painter.fillRect(block.rect(), color); painter.end(); label->setPixmap(pixmap); }
Nous les peignons simplement sur l'étiquette au fur et à mesure qu'ils arrivent.
La classe RenderThread
La classe RenderThread traite une image en créant des objets Block et en utilisant le signal sendBlock(Block) pour les envoyer aux autres composants de l'exemple.
class RenderThread : public QThread { Q_OBJECT public: RenderThread(QObject *parent = nullptr); ~RenderThread(); void processImage(const QImage &image); signals: void sendBlock(const Block &block); protected: void run(); private: QImage m_image; };
Le constructeur et le destructeur ne sont pas cités ici. Ils se chargent de configurer l'état interne du thread et de le nettoyer lorsqu'il est détruit.
Le traitement est lancé par la fonction processImage(), qui appelle la réimplémentation de la fonction QThread::run() de la classe RenderThread:
void RenderThread::processImage(const QImage &image) { if (image.isNull()) return; m_image = image; start(); } void RenderThread::run() { const int size = qMax(m_image.width()/20, m_image.height()/20); for (int s = size; s > 0; --s) { for (int c = 0; c < 400; ++c) {
Ignorant les détails du traitement de l'image, nous constatons que le signal contenant un bloc est émis de la manière habituelle :
...
const Block block(QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1),
QColor(red/n, green/n, blue/n));
emit sendBlock(block);
if (isInterruptionRequested())
return;
msleep(10);
}
}
}Chaque signal émis sera mis en file d'attente et transmis ultérieurement à l'emplacement addBlock(Block) de la fenêtre.
Enregistrement du type
Dans la fonction main() de l'exemple, nous enregistrons la classe Block en tant que type personnalisé avec le système de méta-objets en appelant la fonction template qRegisterMetaType() :
int main(int argc, char *argv[]) { QApplication app(argc, argv) ; qRegisterMetaType<Block>(); Window window ; window.show() ; window.loadImage(createImage(256, 256)) ; return app.exec() ; }
Cet appel est placé ici pour s'assurer que le type est enregistré avant toute connexion de fente de signal qui l'utilise.
Le reste de la fonction main() concerne la définition d'une graine pour le générateur de nombres pseudo-aléatoires, la création et l'affichage de la fenêtre et la définition d'une image par défaut. Voir le code source pour l'implémentation de la fonction createImage().
Pour en savoir plus
Cet exemple a montré comment un type personnalisé peut être enregistré dans le système de méta-objets afin qu'il puisse être utilisé avec des connexions de fentes de signaux entre les threads.
En pratique, la macro Q_DECLARE_METATYPE() et la fonction template qRegisterMetaType() peuvent être utilisées pour enregistrer des types personnalisés, mais qRegisterMetaType() n'est nécessaire que si vous avez besoin d'effectuer une communication par signal ou de créer et détruire des objets du type personnalisé au moment de l'exécution.
De plus amples informations sur l'utilisation des types personnalisés avec Qt sont disponibles dans le document Creating Custom Qt Types (Créer des types Qt personnalisés).
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.