Qt - 用第二个线程更新主窗口 [英] Qt - updating main window with second thread

查看:25
本文介绍了Qt - 用第二个线程更新主窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多线程的 qt 应用程序.当我在 mainwindow.cpp 中做一些进程时,同时我想从其他线程更新 mainwindow.ui.

i have an multithreaded qt application. when i am doing some processes in mainwindow.cpp, at the same time, i want to update mainwindow.ui from other thread.

我有 mythread.h

i have mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include "mainwindow.h"

class mythread : public QThread
{
    public:
        void run();
        mythread( MainWindow* ana );
     MainWindow* ana;
private:

};

#endif // MYTHREAD_H

mythread.cpp

mythread.cpp

mythread::mythread(MainWindow* a)
{
    cout << "thread created" << endl;
        ana = a;
}

void mythread::run()
{
    QPixmap i1 (":/notes/pic/4mdodiyez.jpg");
    QLabel *label = new QLabel();
    label->setPixmap(i1);
    ana->ui->horizontalLayout_4->addWidget(label);


}

但问题是,我无法到达 ana->ui->horizo​​ntalLayout_4->addWidget(label);

but the problem is that, i cannot reach the ana->ui->horizontalLayout_4->addWidget(label);

我该怎么做?

推荐答案

但问题是,我无法到达ana->ui->horizo​​ntalLayout_4->addWidget(label);

but the problem is that, i cannot reach the ana->ui->horizontalLayout_4->addWidget(label);

将您的 UI 修改放在主窗口的一个插槽中,并将线程信号连接到该插槽,很有可能它会起作用.我认为只有主线程可以访问 Qt 中的 UI.因此,如果您想要 GUI 功能,它必须存在,并且只能从其他线程发出信号.

Put your UI modifications in a slot in your main window, and connect a thread signal to that slot, chances are it will work. I think only the main thread has access to the UI in Qt. Thus if you want GUI functionality, it must be there, and can be only signaled from other threads.

好的,这是一个简单的例子.顺便说一句,您的方案并不真正需要扩展 QThread - 所以你最好不要这样做,除非你真的必须这样做.这就是为什么在这个例子中我将使用一个普通的 QThread 和一个基于 QObject 的工作线程,但是如果你子类化 QThread,概念是一样的:

OK, here is a simple example. BTW, your scenario doesn't really require to extend QThread - so you are better off not doing it, unless you really have to. That is why in this example I will use a normal QThread with a QObject based worker instead, but the concept is the same if you subclass QThread:

主界面:

class MainUI : public QWidget
{
    Q_OBJECT

public:
    explicit MainUI(QWidget *parent = 0): QWidget(parent) {
        layout = new QHBoxLayout(this);
        setLayout(layout);
        QThread *thread = new QThread(this);
        GUIUpdater *updater = new GUIUpdater();
        updater->moveToThread(thread);
        connect(updater, SIGNAL(requestNewLabel(QString)), this, SLOT(createLabel(QString)));
        connect(thread, SIGNAL(destroyed()), updater, SLOT(deleteLater()));

        updater->newLabel("h:/test.png");
    }

public slots:
    void createLabel(const QString &imgSource) {
        QPixmap i1(imgSource);
        QLabel *label = new QLabel(this);
        label->setPixmap(i1);
        layout->addWidget(label);
    }

private:
    QHBoxLayout *layout;
};

... 和工作对象:

class GUIUpdater : public QObject {
    Q_OBJECT

public:
    explicit GUIUpdater(QObject *parent = 0) : QObject(parent) {}    
    void newLabel(const QString &image) { emit requestNewLabel(image); }

signals:    
    void requestNewLabel(const QString &);
};

worker 对象被创建并移动到另一个线程,然后连接到创建标签的槽,然后调用它的 newLabel 方法,它只是一个包装器来发出 requestNewLabel 信号并将路径传递给图像.然后将信号从工作对象/线程与图像路径参数一起传递到主 UI 插槽,并将新标签添加到布局中.

The worker object is created and moved to another thread, then connected to the slot that creates the labels, then its newLabel method is invoked, which is just a wrapper to emit the requestNewLabel signal and pass the path to the image. The signal is then passed from the worker object/thread to the main UI slot along with the image path parameter and a new label is added to the layout.

由于工作对象是在没有父对象的情况下创建的,以便能够将其移动到另一个线程,因此我们还将线程销毁信号连接到工作对象 deleteLater() 槽.

Since the worker object is created without parent in order to be able to move it to another thread, we also connect the thread destroyed signal to the worker deleteLater() slot.

这篇关于Qt - 用第二个线程更新主窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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