在Qt中正确的线程方式 [英] Correct way of threading in Qt

查看:132
本文介绍了在Qt中正确的线程方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有时间的图像加载(图像是大),还有一些操作上就完成了加载。我不想阻止应用程序GUI。

I have time consuming image loading (image is big), also some operations on it are done when loading. I do not want to block application GUI.

我的想法是在另一个线程中加载图片,发出加载图片的信号,然后使用此图片重绘视图。

My idea is to load image in another thread, emit signal that image is loaded and then redraw view with this image.

我的方法:

void Window::loadImage()
{ 
    ImageLoader* loaderThread = new ImageLoader();
    connect(loaderThread,SIGNAL(imageLoaded()),this,SLOT(imageLoadingFinished());
    loaderThread->loadImage(m_image, m_imagesContainer, m_path);
}
void Window::imageLoadingFinished()
{
    m_imagesContainer->addImage(m_image);
    redrawView();
}

class ImageLoader : public QThread
{
    Q_OBJECT
    public:
       ImageLoader(QObject *parent = 0) : m_image(NULL), m_container(NULL)

       void loadImage(Image* img, Container* cont, std::string path)
       {
            m_image = img;
            m_container = cont;
            ...
            start();
       }
    signals:
       void imageLoaded();
    protected:
       void run()
       {
           //loading image and operations on it
           emit imageLoaded();
       }
    protected:
       Image* m_image;
       Container* m_container;
}

我基于 quedcustomtype 示例从Qt写这个代码。当在stackoverflow中进行搜索和搜索时,我还发现子类化 QThread 不是一个好主意。

I was basing on quedcustomtype example from Qt writing this code. When googling and searching in stackoverflow I've also find out that subclassing QThread is not a good idea.

所以问题是什么是正确的方法呢?正如我所说,我想要非阻塞的GUI,加载和操作完成在另一个线程和信号,说加载完成。在信号被发出后,视图应该被重绘。
我不知道多线程,但是认为理解或有足够的知识来理解基本的想法。

So the question is what is the correct way to do it? As I said I want non blocking GUI, loading and operations done in another thread and signal which says loading is finished. After signal is emited view should be redrawn. I don't know much about multithreading however think to understand or have sufficient knowledge to understand basic ideas.

推荐答案

我想这是最好的方式:

#include <QApplication>
#include <QLabel>
#include <QThread>

class ImageLoader : public QObject
{
   Q_OBJECT
public:
   ImageLoader() : QObject() {
      moveToThread(&t);
      t.start();
   }
   ~ImageLoader() {
      qDebug("Bye bye!");
      t.quit();
      t.wait();
   }

   void requestImage(QString absPath) {
      QMetaObject::invokeMethod(this, "loadImage", Q_ARG(QString, absPath));
   }

public slots:
   void loadImage(QString absPath) {
      // Simulate large image.
      QImage image(absPath);
      sleep(10);
      qDebug("Image loaded!");
      emit imageReady(image);
   }

signals:
   void imageReady(QImage image);

private:
   QThread t;
};

class MyLabel : public QLabel
{
   Q_OBJECT
public:
   MyLabel() : QLabel() {}

   void mousePressEvent(QMouseEvent* ev) {
      Q_UNUSED(ev);
      qDebug("I got the event!");
   }

public slots:
   void setImage(QImage image) {
      setPixmap(QPixmap::fromImage(image));
      resize(image.width(), image.height());
      qDebug("Image shown!");
   }
};

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);

   MyLabel label;
   label.show();

   ImageLoader imageLoader;
   QObject::connect(&imageLoader, SIGNAL(imageReady(QImage)), &label, SLOT(setImage(QImage)));
   imageLoader.requestImage(some_abs_path);

   return a.exec();
}

#include "main.moc"



也喜欢QtConcurrent,但认为它的使用在某种程度上被劝阻: http: //www.mail-archive.com/development@qt-project.org/msg07794.html

这篇关于在Qt中正确的线程方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆