qt5:如何在qthread中从静态函数创建和显示自定义qdialog

qt5:如何在qthread中从静态函数创建和显示自定义qdialog,qt,static,qthread,qdialog,Qt,Static,Qthread,Qdialog,假设您创建了一个新线程,该线程在静态函数启动后调用静态函数。在该静态函数中,您需要创建并显示自定义qdialog。如何创建它,使其没有父线程且位于正确的线程中 构造函数将父线程设置为0,但仍报告无法在其他线程中为父线程创建子线程的错误。由于它是一个静态函数,我不能使用“this”对象,没有“this”,我无法检索当前线程或线程id。我想我可能可以调用myCustomDialog->moveToThread(),但我不知道如何从静态函数中确定正确的线程 如果我使用其中一个QMessageBox静态

假设您创建了一个新线程,该线程在静态函数启动后调用静态函数。在该静态函数中,您需要创建并显示自定义qdialog。如何创建它,使其没有父线程且位于正确的线程中

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

如果我使用其中一个QMessageBox静态函数,那么一切都可以正常工作。例如,调用QMessageBox::information(0,tr(“Title”),tr(“Message”)不会报告任何错误。如何将自定义qdialog编码为与qmessagebox静态函数类似的函数

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

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
}

不要。从另一个线程创建QWidget对象是个坏主意。各国:

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

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


如另一个答案中所述,如果需要,此连接可以通过将连接类型设置为来阻止工作线程


有关从其他线程调用函数的更多信息,请参阅。

示例。。。您可以调整它以从静态函数调用,但我认为这不是必需的。以下一种方式处理线程是一种很好的做法:您应该在GUI线程中创建对话框,并使用
Qt::BlockingQueuedConnection

工人

#include <QObject>

class Worker
    : public QObject
{
    Q_OBJECT

signals:
    void showDialog();

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

public slots:
    void doLongWork();

private:
};
#包括
班主任
:公共QObject
{
Q_对象
信号:
void showDialog();
公众:
工作者(QObject*parent=NULL);
~Worker();
公众时段:
无效工作();
私人:
};
Worker.cpp

#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();
}
#包括
#包括
#包括
#包括
#包括
工作者::工作者(QObject*父)
:QObject(父对象)
{
}
工人::~Worker()
{
}
void Worker::doLongWork()//您可以使用相同的效果重写QThread::run,但这是一种不好的做法
{

qDebug()我已经考虑过这个选项,但我需要将对话框设置为应用程序阻塞。线程中正在执行的代码只是作为最后手段提示用户输入。当它确实显示对话框时,它需要阻止应用程序继续,直到用户决定要采取的操作。线程包含一个while循环,因此如果我发出信号然后代码可能会继续运行,至少是暂时的,直到对话框可以生成并显示在主线程中。即使如此,我也不确定它是否会在dialog.exec()之后在次线程中暂停while循环已调用。如前所述,您不能从线程访问gui。发送信号并另外设置
QWaitCondition
。这将使线程等待
唤醒
信号。如另一个答案中所述,您可以通过与建立连接来使用
emit
阻止工作线程。如果您有其他r除了主线程和工作线程之外,您需要阻止的线程会稍微复杂一些。感谢提示。使用Qt::BlockingQueuedConnection类型,然后从非gui线程发出信号,效果非常好。Qt::BlockingQueuedConnection上的指针很好。我忘了那个连接类型。
#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 ); // !!!See connection type!!!

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

    return a.exec();
}