假设您创建了一个新线程,然后在启动后调用静态函数。在该静态函数中,您需要创建并显示自定义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
}
答案 0 :(得分:2)
别。从另一个线程创建QWidget对象是个坏主意。 Documentation州:
在GUI应用程序中,主线程也称为GUI线程 因为它是唯一允许执行GUI相关的线程 操作
我通常解决这个问题的方法是在非GUI线程中从我的对象发出一个信号,该信号连接到主线程中的对象(对我来说通常是MainWindow)。接收对象然后在主线程上创建对话框。
如在另一个答案中所提到的,如果需要,此连接可以通过将连接类型设置为Qt::BlockingQueuedConnection来阻止您的工作线程。
有关从其他线程调用函数的更多信息,请参阅this post。
答案 1 :(得分:1)
示例...您可以调整它以通过静态函数进行调用,但我认为这不是必需的。最好以下一种方式使用线程:您应该在GUI线程中创建对话框,并使用Qt::BlockingQueuedConnection
Worker.h
#include <QObject>
class Worker
: public QObject
{
Q_OBJECT
signals:
void showDialog();
public:
Worker( QObject *parent = NULL );
~Worker();
public slots:
void doLongWork();
private:
};
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();
}
的main.cpp
#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();
}
注意:WinAPI MessageBoxes仅用于可视化该线程正在等待关闭对话框。