Qt - 从c ++线程发出信号

时间:2014-07-27 15:14:55

标签: c++ qt signals-slots stdthread emit

我想从Qt中的C ++线程(std :: thread)发出信号。

我该怎么做?

4 个答案:

答案 0 :(得分:11)

您绝对可以从线程(QThreadstd::thread甚至boost::thread)发出信号。只有你必须小心你的连接功能的第五个参数(Qt::ConnectionType):

如果Qt::DirectConnection:当发出信号时,立即(从当前线程)调用插槽。 如果Qt::QueuedConnection:当控制返回到接收者线程的事件循环时调用插槽。插槽在接收器的线程中执行。

有关更多选项,请参阅ConnectionType-enum

问题实际上不是来自哪个线程发出信号,而是更多来自调用插槽的线程。例如,我认为QLabel::setText必须从QLabel的所有者线程(很可能是主线程)执行。因此,如果您从线程发出连接到QLabel的{​​{1}}的信号,则必须与setTextQt::AutoConnectionQt::QueuedConnection建立连接。

答案 1 :(得分:4)

您可能不应该从std::thread创建的线程中发出Qt信号,而不需要小心。请参阅Jpo38's answer:连接类型事项等......

如果线程正在运行一些Qt事件循环,你可能会。见threads and QObject

有一个(特定于Unix的)解决方法,与Unix signals with Qt相同:使用从std::thread到主线程的管道。

但是,正如Joachim Pileborg所评论的那样,你应该制作自己的QThread。它是最简单的,也可能是最短的(在源代码方面),您只需复制并粘贴一些现有示例并根据您的需要进行调整。

请注意AFAIK只有主线程应该进行Qt GUI操作。你不应该在主线程之外使用任何QWidget(etc ...)! (BTW,GTK有相同的限制,至少在Linux上:只有主线程应该使用X Windows system protocols

答案 2 :(得分:1)

如果您要保留指向QObject的指针,那么您可以使用QMetaObject::invokeMethod成员之一http://qt-project.org/doc/qt-5/qmetaobject.html#invokeMethod

可能你必须使用Qt::QueuedConnection所以你的信号将在适当的线程(而不是你的std :: thread)中调用。请记住,您的信号不会立即被调用。

答案 3 :(得分:0)

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();
}