Qt无法弄清楚如何在我的程序中处理我的返回值

时间:2014-10-29 13:19:40

标签: c++ multithreading qt

我已经在网上阅读了有关如何在Qt such as the article here中使用多线程应用程序的各种文章,我注意到Qt也更新了他们关于这个主题的official documentation,但我仍然在努力理解我如何创建一个线程,做一些图像处理并返回一个新的QImage来更新我的GUI。

我正在努力澄清的事情是:

  1. 我在哪里放置连接代码,在大多数示例中,我看到在对象的构造函数中声明的连接。

  2. 为什么连接语句需要这么多行才能完成一个进程?即在我的情况下,我有一个滑块来改变QGraphicsView上图像的饱和度,我想生成一个线程来处理图像像素的操作,然后将格式化的QPixmap返回到我的GUI并运行将新图像绘制到画布的渲染方法(我不认为我可以从我的线程更新我的画布?)

  3. 在第2点之后,这是我为我的线程编写的当前代码(我不是QThread的子类,我认为我正确地遵循文档。)

    WorkerThread.h

    #include "sliders.h"
    
    class WorkerThread : public QObject
    {
        Q_OBJECT
    public:
        WorkerThread();
        ~WorkerThread();
    
    public slots:
        void modifySaturation(const int, const QPixmap);
    
    signals:
        void SaturationChanged(const QPixmap);
    
    private:
        Sliders *slider;
    

    };

    WorkerThread.cpp

    WorkerThread::WorkerThread()
    {
    
    }
    
    WorkerThread::~WorkerThread()
    {
    
    }
    
    // Create a new Sliders object on the thread (declaring in construct would place it on the main thread?)
    // Call the modifySaturation() method in the slider class and store its returned QPixmap into the variable to emit it back to the GUI
    void WorkerThread::modifySaturation(const int value, const QPixmap image)
    {
       slider = new Sliders;
       QPixmap img = slider->modifySaturation(value, image);
       emit resultReady(img);
    }
    

    希望上面的评论能够传达我想要做的事情,将新创建的Pixmap发送回主线程以绘制到GUI。

    我遇到麻烦的步骤是编写逻辑来桥接我的主线程和工作线程之间的连接,到目前为止,我在QThread中创建了一个名为'thread'的mainwindow.h对象,然后在我的mainwindow.cpp中,我执行以下操作:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        // Instanciate a scene object that we can draw to and then set up the ui
        scene  = new QGraphicsScene(this);
        filter = new Filters;
        worker = new WorkerThread;
        ui->setupUi(this);
    
        thread = new QThread;
        worker->moveToThread(&thread);
    
        // This is what I am struggling to understand
        connect(thread, SIGNAL(started()), worker, SLOT(modifySaturation(int,QPixmap)));
        connect(worker, SIGNAL(SaturationChanged(QPixmap)), MainWindow, SLOT(onSaturationChanged()));
    }    
    
    // Public slot on my main window to update the GUI
    void MainWindow::onSaturationChanged(QPixmap)
    {
        // image is a private member describing the current loaded image
        m_image = QPixmap;
        renderImageToCanvas();
    }
    

    根据我的阅读,我应该在开始任务时产生一个新线程,但我怎么能:

    1. 重用这个线程用于多种方法(改变饱和度,改变亮度,改变色调......),我是否需要为每个不同的任务创建一个新线程(这看起来有点复杂)?
    2. 如何连接饱和度滑块的value changed方法以在新线程上启动计算然后返回以使用主窗口中的OnSaturationChanged插槽更新GUI?

1 个答案:

答案 0 :(得分:2)

我会回答你的一个问题,因为Merlin很好地完成了其余的工作。

how can I connect the value changed method of my saturation slider to launch the computation on a new thread and then return it to update the GUI using the OnSaturationChanged slot in my main window?

例如,在您的MainWindow::OnSaturationChanged广告位中,您可以发出一个信号,将QImageslider值传递给您的广告。此信号将连接到WorkerThread的一个插槽,该插槽会进行一些图像处理。

<强> mainwindow.h

public slots:        
    void addNewImage(QImage image);

signals:
    void requestImageUpdate(QImage image, int sliderValue);

<强> mainwindow.cpp

    //in your MainWindow constructor or wherever you create your worker...
    connect(this, SIGNAL(requestImageUpdate(QImage, int)), worker, SLOT(updateImage(QImage, int)));
    connect(worker, SIGNAL(imageUpdated(QImage)), this, SLOT(addNewImage(QImage)));
    ...

void MainWindow::OnSaturationChanged()
{
    emit requestImageUpdate(myImage, slider->value());
}

void MainWindow::addNewImage(QImage image)
{
    //update the image in your graphics view or do whatever you want to do with it
}

<强> workerthread.h

public slots:
    void updateImage(QImage image, int sliderValue);

signals:
    void imageUpdated(QImage newImage);

<强> workerthread.cpp

void WorkerThread::updateImage(QImage image, int sliderValue)
{
    QImage newImage; // you might no need this, this is just an example
    ....
    emit imageUpdated(newImage);
}

P.S。仅在主线程中使用QPixmap。在其他主题中使用QImage