原创文章,欢迎转载。转载请注明:转载自 祥的博客
原文链接:https://blog.csdn.net/humanking7/article/details/86071134
Qt自定义信号signals和emit信号
Qt
调用Matlab Engine
,但是Matlab Engine
打开太慢了,如果放在UI主线程
中会造成界面卡死,所以打算开一个线程去打开Matlab Engine
,当其打开后,向UI主线程
发送signal消息
,当UI主线程
的slot槽
接收到消息后
,就会将Matlab Engine
对应的Matlab Command Window对话框
嵌入到UI主线程
的界面中。
所以本文的所需解决的问题就是:
在一个线程中发送一个
自定义signal信号
,另一线程的slot槽
接收到消息后,进行相应
#include
#include
#include "engine.h"
class threadMatlab : public QThread
{
Q_OBJECT
//自定义信号
signals:
void openMatlabEngine(bool isOpenMatlabEngine); // 用于向主线程发送Matlab Engine是否打开的信号, 在.cpp中,没有进行定义,直接使用emit进行数据的发送
public:
threadMatlab(QObject *parent);
~threadMatlab();
void setMatlabEngine(Engine** pEp);//将Matlab指针的指针传递给它
void quitThead();//退出线程
protected:
void run();
private:
QDialog* m_pParent = nullptr;//父窗口
bool m_isOpenMatlabEngine = false;//是否已经打开了Matlab Engine
Engine** m_pEp = NULL; //指向指针的指针[定义Matlab engine类型指针,往后函数都要用它来指示目标]
bool m_isQuit = false;//是否要退出
};
#include "threadMatlab.h"
threadMatlab::threadMatlab(QObject *parent)
: QThread(parent)
{
m_pParent = (QDialog*)parent;
m_isOpenMatlabEngine = false;
m_isQuit = false;
}
threadMatlab::~threadMatlab()
{
}
void threadMatlab::setMatlabEngine(Engine** pEp)
{
m_pEp = pEp;
}
void threadMatlab::quitThead()
{
m_isQuit = true;
}
void threadMatlab::run()
{
while (true)
{
//是否要退出
if (m_isQuit)
{
break;//退出while
}
//打开Matlab Engine[如果没打开,就一直去打开,直到打开]
if (false == m_isOpenMatlabEngine)//没有打开Matlab Engine
{
(*m_pEp) = engOpen(NULL); //启动Matlab Engine
if ((*m_pEp) != NULL)
{//打开成功
m_isOpenMatlabEngine = true;
// 发送信号
emit openMatlabEngine(m_isOpenMatlabEngine);
engSetVisible((*m_pEp), false);//不显示Matlab Cmd对话框
}
else
{//打开失败
m_isOpenMatlabEngine = false;
// 发送信号
emit openMatlabEngine(m_isOpenMatlabEngine);
}
}
}
}
#include
#include "ui_MatlabCmdDlg.h"
#include
#include
#include
#include
#pragma execution_character_set("utf-8")
#include "threadMatlab.h"
#include "engine.h"
//附加依赖项[下面3行,可以直接在配置中设置]
#pragma comment(lib,"libeng.lib")
#pragma comment(lib,"libmx.lib")
#pragma comment(lib,"libmex.lib")
class MatlabCmdDlg : public QDialog
{
Q_OBJECT
public:
MatlabCmdDlg(QWidget *parent = Q_NULLPTR);
~MatlabCmdDlg();
void openMatlabEngine();//打开Matlab Engine
//....
private:
void closeMatlabEngine();//关闭Matlab Engine
//....
private:
//....
Engine* m_ep = NULL; //定义Matlab engine类型指针,往后函数都要用它来指示目标
threadMatlab* m_pThreadMatlab;//用于打开Matlab Engine
private slots:
void slot_openMatlabEngine(bool isOpenMatlabEngine);
//....
};
#include "MatlabCmdDlg.h"
#include
//...
MatlabCmdDlg::~MatlabCmdDlg()
{
closeMatlabEngine();
if (nullptr != m_pThreadMatlab)
{
disconnect(m_pThreadMatlab, SIGNAL(openMatlabEngine(bool)), this, SLOT(slot_openMatlabEngine(bool)));
m_pThreadMatlab->quitThead();//退出机制
m_pThreadMatlab->quit();
m_pThreadMatlab->wait();
delete m_pThreadMatlab;
}
}
void MatlabCmdDlg::openMatlabEngine()
{
if (nullptr!=m_pThreadMatlab)
{//线程已经打开
return;
}
//创建线程
m_pThreadMatlab = new threadMatlab(this);
// 将Matlab Engine的指针的指针赋值给线程中的变量,让线程去创建Matlab Engine指针
m_pThreadMatlab->setMatlabEngine(&m_ep);
// connect函数,最后一个参数需要注意,不能使用默认
connect(m_pThreadMatlab, SIGNAL(openMatlabEngine(bool)), this, SLOT(slot_openMatlabEngine(bool)), Qt::QueuedConnection);
ui.lab_central->setText("Matlab Engine 正在启动,请稍后...");
m_pThreadMatlab->start();//启动线程就会打开Matlab Engine
}
void MatlabCmdDlg::closeMatlabEngine()
{
//...
}
void MatlabCmdDlg::moveMatlabCmdIntoDlg()
{//将Matlab Engine的窗口 嵌入到本窗口中
//...
}
void MatlabCmdDlg::slot_openMatlabEngine(bool isOpenMatlabEngine)
{//当Matlab 启动后发送消息,主线程接收到消息进行处理
if (isOpenMatlabEngine)
{//Matlab Engine已经打开
ui.lab_central->setText("Matlab Engine 打开成功!");
moveMatlabCmdIntoDlg();//嵌入Matlab Cmd 到本Dlg
}
else
{//Matlab Engine打开失败
ui.lab_central->setText("Matlab Engine 打开失败!");
}
}
//...
自定义信号用关键词signals:
,类似C++
的关键词public、private
等用法一致。
如果要自定义保护信号,就在protected:
后声明。
自定义信号只需要在头文件的类声明中声明, 然后将槽
连接到信号
即可,无需实现信号函数。
信号函数与槽函数的返回值类型
在任何时候都可以不同,而且如果不关心信号传递下来的参数,信号函数与槽函数的参数列表也可以不相同
, 但是如果要访问信号传递下来的任何参数时, 信号函数 与 槽函数 的参数列表必须相同
。
发送信号
只需要用关键字emit
后面加上要发的信号,如果要信号函数是有参数
的,可以通过形参
给槽函数传值。
emit openMatlabEngine(m_isOpenMatlabEngine);
emit openMatlabEngine(true);
emit openMatlabEngine(false);
// connect函数,最后一个参数需要注意,不能使用默认
connect(m_pThreadMatlab, SIGNAL(openMatlabEngine(bool)), this, SLOT(slot_openMatlabEngine(bool)), Qt::QueuedConnection);
这个参数可以用于线程间的信号传递,详细信息见博文:[Qt]connect()参数Qt:ConnectionType使用讲解