QT +如何调用自定制的C ++插槽代码在不同的线程运行(QT + How to call slot

2019-06-26 05:23发布

我是新来QT和我正在做一些学习。

我想触发从一个C ++螺纹(目前的QThread)修改GUI窗口小部件的狭槽。

不幸的是我得到一个:断言失败的:Q_ASSERT(qApp && qApp->线程()==的QThread :: currentThread());

这里是一些代码:

(MAIN + Thread类)

   class mythread : public QThread
    {
    public:
        mythread(mywindow* win){this->w = win;};
        mywindow* w;
        void run()
        {
            w->ui.textEdit->append("Hello");        //<--ASSERT FAIL
            //I have also try to call a slots within mywindow which also fail.
        };
    };

    int main(int argc, char *argv[])
    {
        QApplication* a = new QApplication(argc, argv);
        mywindow* w = new mywindow();

        w->show();
        mythread* thr = new mythread(w);
        thr->start();

        return a->exec();
    }

窗口:

class mywindow : public QMainWindow
{
    Q_OBJECT

public:
    mywindow (QWidget *parent = 0, Qt::WFlags flags = 0);
    ~mywindow ();
    Ui::mywindow ui;

private:



public slots:
    void newLog(QString &log);
};

所以,我在如何通过代码在不同的线程更新GUI部分好奇。

感谢您的帮助

Answer 1:

除了stribika的回答 ,我经常发现它更容易使用的信号/槽连接。 您可以指定,当您将它连接,以避免与线程的信号在其所属对象的上下文中的问题,应该是一个排队的连接。

class mythread : public QThread
{
signals:
    void appendText( QString );
public:

    mythread(mywindow* win){this->w = win;};
    mywindow* w;
    void run()
    {
        emit ( appendText( "Hello" ) );
    };
};

int main(int argc, char *argv[])
{
    QApplication* a = new QApplication(argc, argv);
    mywindow* w = new mywindow();

    w->show();
    mythread* thr = new mythread(w);
    (void)connect( thr, SIGNAL( appendText( QString ) ),
                   w->ui.textEdit, SLOT( append( QString ) ),
                   Qt::QueuedConnection ); // <-- This option is important!
    thr->start();

    return a->exec();
}


Answer 2:

stribika得到它差不多吧:

QMetaObject::invokeMethod( textEdit, "append", Qt::QueuedConnection,
                           Q_ARG( QString, myString ) );

cjhuitt的权利,但:你平时想声明的线程上的信号,并将其连接到append()插槽,以获得对象的生命周期管理的自由(当然,对于一个小接口改变的价格)。 在阿里纳斯的附加参数:

               Qt::QueuedConnection ); // <-- This option is important!

从cjhuitt的答案是没有必要再(它是,在Qt的<= 4.1)时,由于connect()默认为Qt::AutoConnection现在(QT> = 4.2)做正确的事和排队和直接连接模式之间切换的基于上QThread::currentThread()和所述接收器的螺纹亲和力QObjectEMIT时间(而不是在连接时发送者和接收者的亲和力)。



Answer 3:

您需要使用QMetaObject :: invokeMethod中 。 例如:

void MyThread::run() {
    QMetaObject::invokeMethod(label, SLOT(setText(const QString &)), Q_ARG(QString, "Hello"));
}

(以上代码来自这里: http://www.qtforum.org/article/26801/qt4-threads-and-widgets.html )



Answer 4:

我不认为你被允许直接调用的东西,导致从任何其他线程比主线程漆事件。 这将导致崩溃。

我想你可以使用事件循环异步调用的东西,这样的主界面线程拿起,然后做在主线程,这是什么cjhuitt建议更新。



Answer 5:

如果我们的线程关联说什么GUI,但我们不是在GUI线程,也不在QThread的?

我的意思是,一个非调质(通知)线程调用一个QObject的接口方法,在此我们发出自动连接信号。 QObject的的主题亲和力主线程,但该过程实际上是从另一个线程调用。 什么会了Qt在这里做?



文章来源: QT + How to call slot from custom C++ code running in a different thread