如何在另一个线程中显示Qt消息框

10

这是我用的代码:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    testApp w;
    w.show();
    TestClass *test = new TestClass;
    QObject::connect(w.ui.pushButton, SIGNAL(clicked()), test, SLOT(something()));
    return a.exec();
}

TestClass.h

class TestClass: public QObject
{
    Q_OBJECT
    public slots:
        void something()
        {
            TestThread *thread = new TestThread;

            thread -> start();
        }

};

TestThread.h

class TestThread: public QThread
{
    Q_OBJECT
protected:
    void run()
    {
        sleep(1000);
        QMessageBox Msgbox;
        Msgbox.setText("Hello!");
        Msgbox.exec();
    }

};

如果我这样做,会出现错误:

小部件必须在 GUI 线程中创建

我做错了什么?请帮助我。我知道不能在另一个线程中更改 GUI,但我不知道在 Qt 中如何处理这个问题。


3
您可以使用 信号/槽 机制。在主线程中创建消息框,当您想要从线程显示消息时,请从其发出带有要显示的消息的信号。请参阅此处(尽管是针对4.8版本)。 - Adri C.S.
1个回答

9

你做错了什么?

你试图在非 GUI 线程中显示小部件。

如何修复?

class TestClass: public QObject
{
    Q_OBJECT
    public slots:
        void something()
        {
            TestThread *thread = new TestThread();

            // Use Qt::BlockingQueuedConnection !!!
            connect( thread, SIGNAL( showMB() ), this, SLOT( showMessageBox() ), Qt::BlockingQueuedConnection ) ;

            thread->start();
        }
        void showMessageBox()
        {
            QMessageBox Msgbox;
            Msgbox.setText("Hello!");
            Msgbox.exec();
        }
};


class TestThread: public QThread
{
    Q_OBJECT
signals:
    void showMB();
protected:
    void run()
    {
        sleep(1);
        emit showMB();
    }

};

你能解释一下为什么需要使用 BlockingQueuedConnection 吗?我的理解是它会阻塞发射器并等待接收器处理其事件队列。如果你想要防止发射器的堆栈变量在接收器处理信号时超出作用域,那么这很有用,但这里并不相关。它还可以确保发射器线程不会过早结束 - 这是动机吗? - Heath Raftery
2
@HeathRaftery 需要使用 BlockingQueuedConnection 来实现逻辑。在用户与 GUI 线程的消息框交互之前,我们不应该继续执行。 - Dmitry Sazonov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接