It is important to remember that while a QImage can be made outside the GUI thread, this cannot be done for QPixmaps or QWidgets, for example (QPixmaps and QWidgets can only be used in the GUI thread).
The example consists of the following files: main.C, window.C, window.h, thread.C, thread.h, imagewindow.C and imagewindow.h.
main.C
#include <QApplication>
#include "window.h"
//----------------------------------------------------------------------------
//
// main program
//
//----------------------------------------------------------------------------
int main (int argc, char **argv)
{
QApplication app(argc, argv);
Window window;
window.show();
window.setMaximumSize(window.minimumWidth(),
window.minimumHeight());
return app.exec();
}
window.C
Here we make a simple GUI containing just a single button. When the button is clicked, an abstract image is generated in another thread when QThread::start() is called. Using Qt's signals and slots, when the image has been generated, it is sent to the GUI thread and then displayed on the screen.
#include "window.h"
//----------------------------------------------------------------------------
//
// the main GUI
//
//----------------------------------------------------------------------------
//------------
// constructor
//------------
Window::Window(QWidget *parent) : QWidget(parent)
{
setWindowTitle("Qt example 02");
runButton = new QPushButton("Generate image...");
connect(runButton, SIGNAL(clicked()),
this, SLOT(run_thread()));
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(runButton);
setLayout(layout);
// window to display the image
imageWindow = new ImageWindow();
// the QImage generation thread
qRegisterMetaType<QImage>("QImage");
otherThread = new timeConsumingThread();
// slot to respond to the QImage generation thread
// - display the image in a window
connect(otherThread, SIGNAL(theImage(const QImage &)),
this, SLOT(displayImage(const QImage &)));
}
//--------------------
// slot to run thread
//-------------------
void Window::run_thread()
{
if (!otherThread->isRunning())
{
otherThread->start();
}
}
//-------------------
// display the QImage
//-------------------
void Window::displayImage(const QImage &image)
{
imageWindow->plot = QPixmap::fromImage(image);
imageWindow->show();
imageWindow->update();
imageWindow->raise();
imageWindow->activateWindow();
}
window.h
#ifndef WINDOW_H_
#define WINDOW_H_
#include <QPushButton>
#include <QThread>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QMetaType>
#include "thread.h"
#include "imagewindow.h"
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = 0);
private:
QPushButton *runButton;
timeConsumingThread *otherThread;
ImageWindow *imageWindow;
public slots:
void run_thread();
void displayImage(const QImage &);
};
#endif /*WINDOW_H_*/
thread.C
Here we have the time-consuming image generation in the run() reimplementation. In this example, the rendering of the image doesn't actually take too long and is just a very simple abstract image. After the image has been generated, we emit a signal containing the image.
#include "thread.h"
//----------------------------------------------------------------------------
//
// thread which runs the time-consuming image generation
//
//----------------------------------------------------------------------------
//------------
// constructor
//------------
timeConsumingThread::timeConsumingThread(QObject *parent)
: QThread(parent)
{
}
//-----------------------
// run - paint the QImage
//-----------------------
void timeConsumingThread::run()
{
QImage myQImage(600, 600, QImage::Format_RGB32);
QPainter painter(&myQImage);
for (int i=0; i<600; i++)
{
for (int j=0; j<600; j++)
{
double hue = (double)(i + j + i*j)/361200.0;
QColor myColor;
myColor.setHsvF(hue, 1.0, 1.0, 1.0);
painter.setPen(myColor);
painter.drawPoint(i, j);
}
}
emit theImage(myQImage);
}
thread.h
#ifndef THREAD_H_
#define THREAD_H_
#include <QThread>
#include <QImage>
#include <QColor>
#include <QPainter>
class timeConsumingThread : public QThread
{
Q_OBJECT
public:
timeConsumingThread(QObject *parent = 0);
signals:
void theImage(const QImage &);
protected:
void run();
};
#endif /*THREAD_H_*/
imagewindow.C
Here we setup a simple window which is used for displaying the image. In paintEvent() we draw the QPixmap containing our image onto the window.
#include "imagewindow.h"
//----------------------------------------------------------------------------
//
// image window
//
//----------------------------------------------------------------------------
//------------
// constructor
//------------
ImageWindow::ImageWindow(QWidget *parent) : QWidget(parent)
{
setFixedSize(600, 600);
setWindowTitle("Qt Example 02: Image");
}
//-----------------------------------------------------------------------------
//
// paint the image
//
//-----------------------------------------------------------------------------
void ImageWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawPixmap(0, 0, plot);
}
imagewindow.h
#ifndef IMAGEWINDOW_H_This example can be compiled by the following:
#define IMAGEWINDOW_H_
#include <QWidget>
#include <QPixmap>
#include <QPainter>
class ImageWindow : public QWidget
{
Q_OBJECT
public:
ImageWindow(QWidget *parent = 0);
QPixmap plot;
private:
protected:
void paintEvent(QPaintEvent *event);
};
#endif /*IMAGEWINDOW_H_*/
qmake -project
qmake
make
2 comments:
Thanks a lot
nice technique
Post a Comment