krz*_*ych 6 c++ qt multithreading qthread
我有耗时的图像加载(图像很大),加载时也会对其进行一些操作.我不想阻止应用程序GUI.
我的想法是在另一个线程中加载图像,发出加载图像的信号,然后用这个图像重绘视图.
我的方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
我基于quedcustomtypeQt编写此代码的示例.当在stackoverflow中搜索和搜索时,我也发现子类化QThread不是一个好主意.
所以问题是这样做的正确方法是什么?正如我所说,我想要非阻塞GUI,在另一个线程中完成加载和操作,并且信号表示加载完成.信号发出后,应重新绘制视图. 我不太了解多线程,但想要理解或有足够的知识来理解基本思想.
使用QtConcurent框架.
#include <QtConcurentRun>
#include <QFutureWatcher>
//....
class Window: public QWidget /*or something*/
{
//....
private:
QFutureWatcher<QImage> _wacther; //this object will signal when loading finished
};
//...
void Window::loadImage()
{
connect(&_watcher, SIGNAL(finished(), SLOT(finishLoading());
_wacther.setFuture(QtConcurent::run<QImage>(this, &Window::doLoadImage));
}
QImage Window::doLoadImage() //this function will be executed in the new thread. SHOULD BE Thread Safe
{
return someImage;
}
void window::finishLoading()
{
QImage result = _watcher.result();
}
Run Code Online (Sandbox Code Playgroud)
我认为这是最好的方法:
#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"
Run Code Online (Sandbox Code Playgroud)
我也喜欢 QtConcurrent,但认为它的使用在某种程度上不被鼓励:http://www.mail-archive.com/development@qt-project.org/msg07794.html。
| 归档时间: |
|
| 查看次数: |
10599 次 |
| 最近记录: |