Sophie

Sophie

distrib > Mandriva > current > i586 > media > main-updates > by-pkgid > 8e6051afcdb111a0317a58fb64c2abf5 > files > 5917

qt4-doc-4.6.3-0.2mdv2010.2.i586.rpm

<?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">&nbsp;&nbsp;</td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a>&nbsp;&middot; <a href="classes.html"><font color="#004faf">All&nbsp;Classes</font></a>&nbsp;&middot; <a href="functions.html"><font color="#004faf">All&nbsp;Functions</font></a>&nbsp;&middot; <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 &amp;other);
     ~Block();

     Block(const QRect &amp;rect, const QColor &amp;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 &amp;image);

 public slots:
     void addBlock(const Block &amp;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-&gt;setAlignment(Qt::AlignCenter);

     loadButton = new QPushButton(tr(&quot;&amp;Load image...&quot;));
     resetButton = new QPushButton(tr(&quot;&amp;Stop&quot;));
     resetButton-&gt;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(&quot;Queued Custom Type&quot;));
 }</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 &amp;block)
 {
     QColor color = block.color();
     color.setAlpha(64);

     QPainter painter;
     painter.begin(&amp;pixmap);
     painter.fillRect(block.rect(), color);
     painter.end();
     label-&gt;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 &amp;image);

 signals:
     void sendBlock(const Block &amp;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 &amp;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 &gt; 0; --s) {
         for (int c = 0; c &lt; 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&lt;Block&gt;();
     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 &copy; 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>