Type personnalisé en file d'attente
L'exemple « Type personnalisé mis en file d'attente » montre comment transmettre des types personnalisés entre des threads à l'aide de signaux et de slots mis en file d'attente.

Présentation
Dans cet exemple, nous créons une classe de valeur, Block, et l'enregistrons dans le système de méta-objets afin de pouvoir envoyer des instances de cette classe entre des threads à l'aide de signaux et de slots mis en file d'attente.
La classe de blocs
La classe ` Block ` fournit le constructeur par défaut, le constructeur de copie et un destructeur dans la section publique de la classe, comme l'exige le système de méta-objets. Cette 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 tout de même l'enregistrer auprès du système de méta-objets lors de l'exécution en appelant la fonction modèle ` qRegisterMetaType()` avant d'établir toute connexion signal-slot utilisant ce type. Même si nous n'avons pas l'intention d'utiliser ce type avec ` QVariant ` dans cet exemple, il est recommandé de déclarer également le nouveau type avec ` Q_DECLARE_METATYPE()`.
L’implémentation de la classe ` Block ` est triviale ; nous ne la reproduirons donc pas ici.
La classe Window
Nous définissons une classe ` Window ` simple dotée d’un slot public qui accepte un objet ` Block `. Le reste de la classe est dédié à la gestion de l’interface utilisateur et au traitement 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 ` au slot ` addBlock(Block) ` de la fenêtre.
Les parties les plus pertinentes de la classe ` Window ` sont le constructeur et le slot ` addBlock(Block) `.
Le constructeur crée un thread pour le rendu des images et configure une interface utilisateur contenant une étiquette et deux boutons relié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 relions un signal de l'objet ` RenderThread ` au slot ` addBlock(Block) ` de la fenêtre.
...
setWindowTitle(tr("Queued Custom Type"));
}Le reste du constructeur se contente de configurer la mise en page de la fenêtre.
Le slot « addBlock(Block) » reçoit des blocs provenant du thread de rendu via la connexion signal-slot é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 nous contentons de les afficher sur l'étiquette au fur et à mesure de leur arrivée.
La classe RenderThread
La classe ` RenderThread ` traite une image, crée des objets ` Block ` et utilise le signal ` sendBlock(Block) ` pour les envoyer à d'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 présentés ici. Ceux-ci 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) {Sans entrer dans les détails du traitement de l’image, on constate 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 puis transmis ultérieurement au slot « addBlock(Block) » de la fenêtre.
Enregistrement du type
Dans la fonction ` main() ` de l'exemple, nous procédons à l'enregistrement de la classe ` Block ` en tant que type personnalisé auprès du système de méta-objets en appelant la fonction modèle ` 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 garantir que le type soit enregistré avant que ne soient établies les connexions signal-slot qui l'utilisent.
Le reste de la fonction ` main() ` sert à définir une graine pour le générateur de nombres pseudo-aléatoires, à créer et afficher la fenêtre, ainsi qu'à définir une image par défaut. Consultez le code source pour découvrir l'implémentation de la fonction ` createImage() `.
Pour en savoir plus
Cet exemple a montré comment enregistrer un type personnalisé dans le système de méta-objets afin de pouvoir l'utiliser avec des connexions signal-slot entre des threads.
En pratique, la macro ` Q_DECLARE_METATYPE()` et la fonction modèle ` qRegisterMetaType()` peuvent toutes deux être utilisées pour enregistrer des types personnalisés, mais ` qRegisterMetaType()` n'est nécessaire que si vous devez effectuer une communication signal-slot ou créer et détruire des objets du type personnalisé lors de l'exécution.
Vous trouverez plus d’informations sur l’utilisation des types personnalisés avec Qt dans le document Création de 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.