Tipo personalizado en cola
El ejemplo de tipo personalizado en cola muestra cómo enviar tipos personalizados entre subprocesos con señales y ranuras en cola.

Visión general
En este ejemplo, creamos una clase de valor, Block, y la registramos en el sistema de meta-objetos para poder enviar instancias de la misma entre subprocesos utilizando señales en cola y ranuras.
La clase Block
La clase Block proporciona un constructor por defecto, un constructor de copia y un destructor en la sección pública de la clase, tal y como requiere el sistema de meta-objetos. La clase describe un rectángulo coloreado.
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);
Tendremos que registrarlo en el sistema de meta-objetos en tiempo de ejecución llamando a la función de plantilla qRegisterMetaType() antes de realizar cualquier conexión de ranura de señal que utilice este tipo. Aunque no tengamos intención de utilizar el tipo con QVariant en este ejemplo, es una buena práctica declarar también el nuevo tipo con Q_DECLARE_METATYPE().
La implementación de la clase Block es trivial, por lo que evitamos citarla aquí.
La clase Window
Definimos una simple clase Window con un slot público que acepta un objeto Block. El resto de la clase se ocupa de gestionar la interfaz de usuario y manejar las imágenes.
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 clase Window también contiene un hilo trabajador, proporcionado por un objeto RenderThread. Este emitirá señales para enviar objetos Block al slot addBlock(Block) de la ventana.
Las partes de la clase Window más relevantes son el constructor y la ranura addBlock(Block).
El constructor crea un hilo para renderizar imágenes, configura una interfaz de usuario que contiene una etiqueta y dos botones pulsadores que están conectados a ranuras de la misma clase.
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);
En la última de estas conexiones, conectamos una señal en el objeto RenderThread a la ranura addBlock(Block) de la ventana.
...
setWindowTitle(tr("Queued Custom Type"));
}El resto del constructor simplemente configura el diseño de la ventana.
La ranura addBlock(Block) recibe bloques del hilo de renderizado a través de la conexión señal-ranura establecida en el constructor:
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); }
Simplemente los pintamos en la etiqueta a medida que llegan.
La clase RenderThread
La clase RenderThread procesa una imagen, creando objetos Block y utilizando la señal sendBlock(Block) para enviarlos a otros componentes del ejemplo.
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; };
El constructor y el destructor no se citan aquí. Estos se encargan de configurar el estado interno del hilo y de limpiarlo cuando se destruye.
El procesamiento se inicia con la función processImage(), que llama a la reimplementación de la clase RenderThread de la función QThread::run():
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) {
Ignorando los detalles de la forma en que se procesa la imagen, vemos que la señal que contiene un bloque se emite de la forma habitual:
...
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);
}
}
}Cada señal que se emita se pondrá en cola y se entregará más tarde a la ranura addBlock(Block) de la ventana.
Registro del tipo
En la función main() del ejemplo, realizamos el registro de la clase Block como un tipo personalizado con el sistema de meta-objetos llamando a la función de plantilla 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(); }
Esta llamada se coloca aquí para asegurar que el tipo está registrado antes de que se realice cualquier conexión de ranura de señal que lo utilice.
El resto de la función main() se ocupa de establecer una semilla para el generador de números pseudoaleatorios, crear y mostrar la ventana, y establecer una imagen por defecto. Véase el código fuente para la implementación de la función createImage().
Más información
Este ejemplo mostró cómo un tipo personalizado puede ser registrado con el sistema de meta-objetos para que pueda ser utilizado con conexiones de ranura de señal entre hilos.
En la práctica, tanto la macro Q_DECLARE_METATYPE() como la función de plantilla qRegisterMetaType() pueden usarse para registrar tipos personalizados, pero qRegisterMetaType() sólo es necesaria si necesitas realizar una comunicación signal-slot o necesitas crear y destruir objetos del tipo personalizado en tiempo de ejecución.
Puede encontrar más información sobre el uso de tipos personalizados con Qt en el documento Creación de tipos personalizados de Qt.
© 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.