<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <!-- queuedcustomtype.qdoc --> <head> <title>Qt 4.6: Queued Custom Type Example</title> <link href="classic.css" rel="stylesheet" type="text/css" /> </head> <body> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> <td align="left" valign="top" width="32"><a href="http://qt.nokia.com/"><img src="images/qt-logo.png" align="left" border="0" /></a></td> <td width="1"> </td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a> · <a href="classes.html"><font color="#004faf">All Classes</font></a> · <a href="functions.html"><font color="#004faf">All Functions</font></a> · <a href="overviews.html"><font color="#004faf">Overviews</font></a></td></tr></table><h1 class="title">Queued Custom Type Example<br /><span class="subtitle"></span> </h1> <p>Files:</p> <ul> <li><a href="threads-queuedcustomtype-block-cpp.html">threads/queuedcustomtype/block.cpp</a></li> <li><a href="threads-queuedcustomtype-block-h.html">threads/queuedcustomtype/block.h</a></li> <li><a href="threads-queuedcustomtype-renderthread-cpp.html">threads/queuedcustomtype/renderthread.cpp</a></li> <li><a href="threads-queuedcustomtype-renderthread-h.html">threads/queuedcustomtype/renderthread.h</a></li> <li><a href="threads-queuedcustomtype-window-cpp.html">threads/queuedcustomtype/window.cpp</a></li> <li><a href="threads-queuedcustomtype-window-h.html">threads/queuedcustomtype/window.h</a></li> <li><a href="threads-queuedcustomtype-main-cpp.html">threads/queuedcustomtype/main.cpp</a></li> <li><a href="threads-queuedcustomtype-queuedcustomtype-pro.html">threads/queuedcustomtype/queuedcustomtype.pro</a></li> </ul> <p>The Queued Custom Type example shows how to send custom types between threads with queued signals and slots.</p> <p align="center"><img src="images/queuedcustomtype-example.png" /></p><p>Contents:</p> <ul><li><a href="#overview">Overview</a></li> <li><a href="#the-block-class">The Block Class</a></li> <li><a href="#the-window-class">The Window Class</a></li> <li><a href="#the-renderthread-class">The RenderThread Class</a></li> <li><a href="#registering-the-type">Registering the Type</a></li> <li><a href="#further-reading">Further Reading</a></li> </ul> <a name="overview"></a> <h2>Overview</h2> <p>In the <a href="tools-customtypesending.html">Custom Type Sending Example</a>, we showed how to use a custom type with signal-slot communication within the same thread.</p> <p>In this example, we create a new value class, <tt>Block</tt>, and register it with the meta-object system to enable us to send instances of it between threads using queued signals and slots.</p> <a name="the-block-class"></a> <h2>The Block Class</h2> <p>The <tt>Block</tt> class is similar to the <tt>Message</tt> class described in the <a href="tools-customtype.html">Custom Type Example</a>. It provides the default constructor, copy constructor and destructor in the public section of the class that the meta-object system requires. It describes a colored rectangle.</p> <pre> 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);</pre> <p>We will still need to register it with the meta-object system at run-time by calling the <a href="qmetatype.html#qRegisterMetaType">qRegisterMetaType</a>() template function before we make any signal-slot connections that use this type. Even though we do not intend to use the type with <a href="qvariant.html">QVariant</a> in this example, it is good practice to also declare the new type with <a href="qmetatype.html#Q_DECLARE_METATYPE">Q_DECLARE_METATYPE</a>().</p> <p>The implementation of the <tt>Block</tt> class is trivial, so we avoid quoting it here.</p> <a name="the-window-class"></a> <h2>The Window Class</h2> <p>We define a simple <tt>Window</tt> class with a public slot that accepts a <tt>Block</tt> object. The rest of the class is concerned with managing the user interface and handling images.</p> <pre> class Window : public QWidget { Q_OBJECT public: Window(); 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; };</pre> <p>The <tt>Window</tt> class also contains a worker thread, provided by a <tt>RenderThread</tt> object. This will emit signals to send <tt>Block</tt> objects to the window's <tt>addBlock(Block)</tt> slot.</p> <p>The parts of the <tt>Window</tt> class that are most relevant are the constructor and the <tt>addBlock(Block)</tt> slot.</p> <p>The constructor creates a thread for rendering images, sets up a user interface containing a label and two push buttons that are connected to slots in the same class.</p> <pre> Window::Window() { thread = new RenderThread(); label = new QLabel(); label->setAlignment(Qt::AlignCenter); loadButton = new QPushButton(tr("&Load image...")); resetButton = new QPushButton(tr("&Stop")); resetButton->setEnabled(false); connect(loadButton, SIGNAL(clicked()), this, SLOT(loadImage())); connect(resetButton, SIGNAL(clicked()), thread, SLOT(stopProcess())); connect(thread, SIGNAL(finished()), this, SLOT(resetUi())); connect(thread, SIGNAL(sendBlock(Block)), this, SLOT(addBlock(Block)));</pre> <p>In the last of these connections, we connect a signal in the <tt>RenderThread</tt> object to the <tt>addBlock(Block)</tt> slot in the window.</p> <pre> ... setWindowTitle(tr("Queued Custom Type")); }</pre> <p>The rest of the constructor simply sets up the layout of the window.</p> <p>The <tt>addBlock(Block)</tt> slot receives blocks from the rendering thread via the signal-slot connection set up in the constructor:</p> <pre> 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); }</pre> <p>We simply paint these onto the label as they arrive.</p> <a name="the-renderthread-class"></a> <h2>The RenderThread Class</h2> <p>The <tt>RenderThread</tt> class processes an image, creating <tt>Block</tt> objects and using the <tt>sendBlock(Block)</tt> signal to send them to other components in the example.</p> <pre> class RenderThread : public QThread { Q_OBJECT public: RenderThread(QObject *parent = 0); ~RenderThread(); void processImage(const QImage &image); signals: void sendBlock(const Block &block); public slots: void stopProcess(); protected: void run(); private: bool m_abort; QImage m_image; QMutex mutex; };</pre> <p>The constructor and destructor are not quoted here. These take care of setting up the thread's internal state and cleaning up when it is destroyed.</p> <p>Processing is started with the <tt>processImage()</tt> function, which calls the <tt>RenderThread</tt> class's reimplementation of the <a href="qthread.html#run">QThread::run</a>() function:</p> <pre> void RenderThread::processImage(const QImage &image) { if (image.isNull()) return; m_image = image; m_abort = false; start(); } void RenderThread::run() { 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) {</pre> <p>Ignoring the details of the way the image is processed, we see that the signal containing a block is emitted in the usual way:</p> <pre> ... Block block(QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), QColor(red/n, green/n, blue/n)); emit sendBlock(block); if (m_abort) return; msleep(10); } } }</pre> <p>Each signal that is emitted will be queued and delivered later to the window's <tt>addBlock(Block)</tt> slot.</p> <a name="registering-the-type"></a> <h2>Registering the Type</h2> <p>In the example's <tt>main()</tt> function, we perform the registration of the <tt>Block</tt> class as a custom type with the meta-object system by calling the <a href="qmetatype.html#qRegisterMetaType">qRegisterMetaType</a>() template function:</p> <pre> int main(int argc, char *argv[]) { QApplication app(argc, argv); qRegisterMetaType<Block>(); qsrand(QTime::currentTime().elapsed()); Window window; window.show(); window.loadImage(createImage(256, 256)); return app.exec(); }</pre> <p>This call is placed here to ensure that the type is registered before any signal-slot connections are made that use it.</p> <p>The rest of the <tt>main()</tt> function is concerned with setting a seed for the pseudo-random number generator, creating and showing the window, and setting a default image. See the source code for the implementation of the <tt>createImage()</tt> function.</p> <a name="further-reading"></a> <h2>Further Reading</h2> <p>This example showed how a custom type can be registered with the meta-object system so that it can be used with signal-slot connections between threads. For ordinary communication involving direct signals and slots, it is enough to simply declare the type in the way described in the <a href="tools-customtypesending.html">Custom Type Sending Example</a>.</p> <p>In practice, both the <a href="qmetatype.html#Q_DECLARE_METATYPE">Q_DECLARE_METATYPE</a>() macro and the <a href="qmetatype.html#qRegisterMetaType">qRegisterMetaType</a>() template function can be used to register custom types, but <a href="qmetatype.html#qRegisterMetaType">qRegisterMetaType</a>() is only required if you need to perform signal-slot communication or need to create and destroy objects of the custom type at run-time.</p> <p>More information on using custom types with Qt can be found in the <a href="custom-types.html">Creating Custom Qt Types</a> document.</p> <p /><address><hr /><div align="center"> <table width="100%" cellspacing="0" border="0"><tr class="address"> <td width="40%" align="left">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td> <td width="20%" align="center"><a href="trademarks.html">Trademarks</a></td> <td width="40%" align="right"><div align="right">Qt 4.6.3</div></td> </tr></table></div></address></body> </html>