Qt - 用第二个线程更新主窗口

abb*_*bby 17 c++ qt multithreading

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

我有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
Run Code Online (Sandbox Code Playgroud)

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);


}
Run Code Online (Sandbox Code Playgroud)

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

我怎样才能做到这一点?

dte*_*ech 17

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

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

好的,这是一个简单的例子.顺便说一下,你的场景并不需要延伸QThread- 所以你最好不要这样做,除非你真的需要.这就是为什么在这个例子中,我将使用一个正常的QThread一个QObject基于工人代替,但概念是相同的,如果你的子类QThread:

主UI:

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;
};
Run Code Online (Sandbox Code Playgroud)

......和工人对象:

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 &);
};
Run Code Online (Sandbox Code Playgroud)

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

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


g19*_*tic 5

首先,“你做错了”。通常,您希望创建一个从 QObject 派生的类,并将该类移动到新的线程对象,而不是从 Qthread 派生您的类

现在要了解您的问题的具体情况,您无法从单独的线程直接修改主 GUI 线程的 ui 元素。您必须从第二个线程到主线程中的connecta 。您可以通过此信号/槽连接传递所需的任何数据,但您无法直接修改 ui 元素(老实说,如果您打算将应用程序的前端与后端分开,您可能不希望这样做)。查看 Qt 的信号和槽文档以获取更多信息signalslot