首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >qt5:如何从q线程中的静态函数创建和显示自定义q对话框

qt5:如何从q线程中的静态函数创建和显示自定义q对话框
EN

Stack Overflow用户
提问于 2013-07-30 15:35:21
回答 2查看 3K关注 0票数 2

假设您已经创建了一个新线程,然后在它启动后调用一个静态函数。在这个静态函数中,您需要创建和显示一个自定义q对话框。如何创建它,使其没有父线程,并且位于正确的线程中?

构造函数将父函数设置为0,但它仍然报告一个错误,即无法在另一个线程中为父线程创建子节点。因为它是一个静态函数,所以我不能使用"this“对象,而没有"this”,我就无法检索当前的线程或线程id。我想我可以调用myCustomDialog->moveToThread(),但是我不知道如何从静态函数中确定正确的线程。

如果我使用一个QMessageBox静态函数,一切都可以正常工作。例如,调用QMessageBox::information(0,tr("Title"),tr("Message"))不会报告任何错误。如何将我的自定义q对话框编码为类似于qmessagebox静态函数的功能?

有任何方法从qApp对象中检索所有正在运行的线程的列表吗?还有其他建议吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static int myFunction();

int myObject::myFunction()
{
    myCustomDialog *mcd = new myCustomDialog();
    // as soon as I call exec() it reports an error and crashes
    mcd->exec();
    // QObject: Cannot create children for a parent that is in a different thread.

    // can't call mcd->moveToThread() without knowing the current thread
    // how can I determine the current thread from this static function?
    // if parent = 0 then why is this error occurring?
    return 0;
}

myCustomDialog(QWidget *parent = 0);

myCustomDialog::myCustomDialog(QWidget *parent) : QDialog(parent)
{
    // create widgets and layout here
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-30 23:32:02

样本..。您可以对其进行调整,以便从静态函数进行调用,但我不认为它是必要的。用下一种方式处理线程是很好的做法:您应该在GUI线程中创建对话框,并使用Qt::BlockingQueuedConnection将它的exec()槽连接到信号

Worker.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <QObject>

class Worker
    : public QObject
{
    Q_OBJECT

signals:
    void showDialog();

public:
    Worker( QObject *parent = NULL );
    ~Worker();

public slots:
    void doLongWork();

private:
};

Worker.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <QThread>
#include <QMessageBox>
#include <QDebug>
#include <QCoreApplication>

#include <Windows.h>


Worker::Worker( QObject *parent )
    : QObject( parent )
{
}

Worker::~Worker()
{
}

void Worker::doLongWork() // You may override QThread::run with same effect, but it is bad practice
{
    qDebug() << "Worker thread id = " << QThread::currentThreadId();
    ::MessageBoxA( NULL, "Click to show dialog in 3 seconds", NULL, 0 );
    ::Sleep( 3000 );
    emit showDialog();  // "Showing" dialog from non-GUI thread. And wait for close
    ::MessageBoxA( NULL, "Dialog closed!", NULL, 0 );
    qApp->quit();
}

main.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <QApplication>
#include <QDialog>
#include <QThread>
#include <QDebug>

#include "Worker.h"


int main(int argc, char *argv[])
{
    QApplication a( argc, argv );
    a.setQuitOnLastWindowClosed( false );

    QDialog dlg;
    QThread workerThread;
    Worker worker;

    qDebug() << "Main thread id = " << QThread::currentThreadId();

    QObject::connect( &workerThread, SIGNAL( started() ), &worker, SLOT( doLongWork() ) );
    QObject::connect( &worker, SIGNAL( showDialog() ), &dlg, SLOT( exec() ), Qt::BlockingQueuedConnection ); // !connection type!

    worker.moveToThread( &workerThread );
    workerThread.start();

    return a.exec();
}

注意: WinAPI MessageBoxes只用于可视化线程确实在等待对话框的关闭。

票数 1
EN

Stack Overflow用户

发布于 2013-07-30 16:03:20

不要。从另一个线程创建QWidget对象是个坏主意。文档指出:

在GUI应用程序中,主线程也称为GUI线程,因为它是唯一允许执行GUI相关操作的线程。

我通常的解决方法是在非GUI线程中从我的对象发出一个信号,该线程连接到主线程中的一个对象(通常是MainWindow )。接收对象然后在主线程上创建对话框。

正如在另一个答案中提到的,如果需要,此连接可以通过将连接类型设置为Qt::BlockingQueuedConnection来阻塞工作线程。

有关从其他线程调用函数的更多信息,请参见这个职位

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17959240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文