【发布时间】:2012-11-01 19:57:43
【问题描述】:
是的,我知道你不能在非 GUI 线程中使用 GUI 的东西。但是,能够创建一个 QWidget 对象,将它发送到 GUI 线程,然后向它发送信号似乎是合理的。但是,当我尝试这样做时,我收到无法移动小部件的错误。但是,这似乎有效:
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QDialog>
class BasicViewer : public QDialog
{
Q_OBJECT
public:
void Function(const float a)
{
std::cout << a << std::endl;
}
};
struct BasicViewerWrapper : public QObject
{
Q_OBJECT
public:
BasicViewer WrappedBasicViewer;
void Function(const float a)
{
WrappedBasicViewer.Function(a);
}
};
#include "main.moc" // For CMake's automoc
void Function2()
{
BasicViewerWrapper basicViewerWrapper;
basicViewerWrapper.moveToThread(QCoreApplication::instance()->thread());
basicViewerWrapper.Function(2.0f);
}
void Function1()
{
Function2();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(Function1);
std::cout << "End" << std::endl;
return app.exec();
}
我创建了一个与 QWidget 具有相同 API 的包装类,它存储了我想直接创建的 QWidget 的实例。我被允许创建该包装器,将其移动到 GUI 线程,然后使用它。我的问题是,有没有办法做到这一点而不必编写这个包装器?这似乎很乏味,而且由于这个概念有效,我不明白为什么不能直接完成。有什么想法吗?
----------- 编辑 ---------------
第一个例子很糟糕,因为它没有尝试对 GUI 元素做任何事情。此示例确实会生成“无法为位于不同线程中的父级创建子级。”
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class BasicViewer : public QMessageBox
{
Q_OBJECT
public:
};
struct BasicViewerWrapper : public QObject
{
Q_OBJECT
public:
BasicViewer WrappedBasicViewer;
void exec()
{
WrappedBasicViewer.exec();
}
};
#include "main.moc" // For CMake's automoc
void Function2()
{
BasicViewerWrapper basicViewerWrapper;
basicViewerWrapper.moveToThread(QCoreApplication::instance()->thread());
basicViewerWrapper.exec();
}
void Function1()
{
Function2();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(Function1);
return app.exec();
}
----------- 编辑 2 ----
我认为这会起作用,因为成员对象是在 Wrapper 的线程被移动之后创建的:
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class BasicViewer : public QMessageBox
{
Q_OBJECT
public:
};
struct BasicViewerWrapper : public QObject
{
Q_OBJECT
public:
BasicViewer* WrappedBasicViewer;
void exec()
{
WrappedBasicViewer->exec();
}
void create()
{
WrappedBasicViewer = new BasicViewer;
}
};
#include "main.moc" // For CMake's automoc
void Function2()
{
BasicViewerWrapper basicViewerWrapper;
basicViewerWrapper.moveToThread(QCoreApplication::instance()->thread());
basicViewerWrapper.create();
basicViewerWrapper.exec();
}
void Function1()
{
Function2();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(Function1);
return app.exec();
}
不幸的是,它没有。谁能解释一下为什么?
--------------- 编辑 3 --------
我不确定为什么会这样?它使用信号触发GUI组件,但GUI对象(QDialog)不是还在非GUI线程中创建吗?
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class DialogHandler : public QObject
{
Q_OBJECT
signals:
void MySignal(int* returnValue);
public:
DialogHandler()
{
connect( this, SIGNAL( MySignal(int*) ), this, SLOT(MySlot(int*)), Qt::BlockingQueuedConnection );
}
void EmitSignal(int* returnValue)
{
emit MySignal(returnValue);
}
public slots:
void MySlot(int* returnValue)
{
std::cout << "input: " << *returnValue << std::endl;
QMessageBox* dialog = new QMessageBox;
dialog->addButton(QMessageBox::Yes);
dialog->addButton(QMessageBox::No);
dialog->setText("Test Text");
dialog->exec();
int result = dialog->result();
if(result == QMessageBox::Yes)
{
*returnValue = 1;
}
else
{
*returnValue = 0;
}
delete dialog;
}
};
#include "main.moc" // For CMake's automoc
void MyFunction()
{
DialogHandler* dialogHandler = new DialogHandler;
dialogHandler->moveToThread(QCoreApplication::instance()->thread());
int returnValue = -1;
dialogHandler->EmitSignal(&returnValue);
std::cout << "returnValue: " << returnValue << std::endl;
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(MyFunction);
std::cout << "End" << std::endl;
return app.exec();
}
【问题讨论】:
标签: multithreading qt qt4