[英]Qt - emit a signal from a c++ thread
I want to emit a signal from a C++ thread (std::thread) in Qt. 我想从Qt中的C ++线程(std :: thread)发出信号。
How can I do it? 我该怎么做?
You definitely can emit a signal from a thread ( QThread
, std::thread
or even boost::thread
). 你绝对可以从线程发出信号(
QThread
, std::thread
甚至boost::thread
)。 Only you must be careful of your connect function's fifth parameter ( Qt::ConnectionType
): 只有你必须小心你的connect函数的第五个参数(
Qt::ConnectionType
):
If Qt::DirectConnection
: The slot is invoked immediately (from the current thread), when the signal is emitted. 如果
Qt::DirectConnection
:立即调用插槽(从当前线程),则发出信号。 If Qt::QueuedConnection
: The slot is invoked when control returns to the event loop of the receiver's thread. 如果
Qt::QueuedConnection
:当控制返回到接收者线程的事件循环时调用该槽。 The slot is executed in the receiver's thread. 插槽在接收器的线程中执行。
See ConnectionType-enum for more options. 有关更多选项,请参阅ConnectionType-enum 。
The problem is not really from which thread you emit the signal, it's more from which thread the slot is being invoked. 问题不在于您从哪个线程发出信号,而是从调用插槽的哪个线程开始。 For instance, I think
QLabel::setText
must be executed from QLabel
's owner thread (most likely main thread). 例如,我认为
QLabel::setText
必须从QLabel
的所有者线程(很可能是主线程)执行。 So if you emit a signal connected to a QLabel
's setText
from a thread, connection must be done with Qt::AutoConnection
, Qt::QueuedConnection
or Qt::BlockingQueuedConnection
. 因此,如果从线程发出连接到
QLabel
的setText
的信号,则必须使用Qt::AutoConnection
, Qt::QueuedConnection
或Qt::BlockingQueuedConnection
。
You probably should not emit a Qt signal from a std::thread
-created thread in general without care. 您可能不应该小心地从
std::thread
-created线程发出Qt信号。 See Jpo38's answer : connection type matters, etc... 见Jpo38的答案 :连接类型很重要等等......
If the thread is running some Qt event loop, you probably could. 如果线程正在运行一些Qt事件循环,你可能会。 See threads and QObject
请参阅线程和QObject
There is a (Unix-specific probably) work-around, doing the same as for Unix signals with Qt : use a pipe from your std::thread
to the main thread. 有一个(特定于Unix的)解决方法, 与使用Qt的Unix信号相同:使用从
std::thread
到主线程的管道。
But, as commented by Joachim Pileborg , you should make your own QThread . 但是,正如Joachim Pileborg评论的那样 ,你应该制作自己的QThread 。 It is the simplest, and probably the shortest (in term of source code), and you just need to copy and paste some existing example and adapt it to your need.
它是最简单的,也可能是最短的(在源代码方面),您只需复制并粘贴一些现有示例并根据您的需要进行调整。
Beware that AFAIK only the main thread should do Qt GUI manipulations. 请注意,AFAIK只有主线程才能进行Qt GUI操作。 You should not use any QWidget (etc...) outside of the main thread!
你不应该在主线程之外使用任何QWidget(etc ...)! (BTW, GTK has the same restriction, at least on Linux: only the main thread is supposed to use the X Windows system protocols )
(顺便说一句,GTK有相同的限制,至少在Linux上:只有主线程应该使用X Windows系统协议 )
If you're keeping pointer to your QObject then you could use one of QMetaObject::invokeMethod
member http://qt-project.org/doc/qt-5/qmetaobject.html#invokeMethod 如果您保持指向QObject的指针,那么您可以使用
QMetaObject::invokeMethod
成员之一http://qt-project.org/doc/qt-5/qmetaobject.html#invokeMethod
Probably you will have to use Qt::QueuedConnection
so your signal will be invoked at proper thread (not your std::thread). 可能你必须使用
Qt::QueuedConnection
所以你的信号将在适当的线程(而不是你的std :: thread)调用。 Remember that your signal won't be invoked immedietly. 请记住,您的信号不会立即被调用。
class MainForm : public QMainWindow
{
Q_OBJECT
public:
explicit MainForm(QWidget *parent = nullptr);
virtual ~MainForm();
private:
signals:
void signalSendButtonEnable(bool);
private slots:
void singalReceiveButtonEnable(bool);
};
MainForm::MainForm(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainForm), status_{false}, io_context_{}, timer_{io_context_}
{
ui->setupUi(this);
// bind SIGNAL & SLOT
connect(this, SIGNAL(signalSendButtonEnable(bool)), this, SLOT(singalReceiveButtonEnable(bool)));
}
MainForm::~MainForm()
{
delete ui;
}
void MainForm::singalReceiveButtonEnable(bool status){ //recv signal
qDebug() << "singalReceiveButtonEnable";
this->ui->btnConnect->setEnabled(status);
}
void MainForm::start(){
std::thread t([](){
sleep(20);
emit signalSendButtonEnable(true); //send signal
});
t.detach();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.