[Qt]自定义信号signals和emit信号



原创文章,欢迎转载。转载请注明:转载自 祥的博客

原文链接:https://blog.csdn.net/humanking7/article/details/86071134


文章目录

    • @[toc]
  • 1.问题来源
  • 2.代码
    • 2.1. 子线程代码
      • 头文件 threadMatlab.h
      • 源文件 threadMatlab.cpp
    • 2.2. 主线程代码
      • 头文件
      • 源文件
  • 3. 讲解
    • 3.1. 整体程序信号流程
    • 3.2. 信号说明
    • 3.3. connect说明

Qt自定义信号signals和emit信号

1.问题来源

Qt调用Matlab Engine,但是Matlab Engine打开太慢了,如果放在UI主线程中会造成界面卡死,所以打算开一个线程去打开Matlab Engine,当其打开后,向UI主线程发送signal消息,当UI主线程slot槽接收到消息后,就会将Matlab Engine对应的Matlab Command Window对话框嵌入到UI主线程的界面中。

所以本文的所需解决的问题就是:

在一个线程中发送一个自定义signal信号,另一线程的slot槽接收到消息后,进行相应

2.代码

2.1. 子线程代码

头文件 threadMatlab.h

#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;//是否要退出
};

源文件 threadMatlab.cpp

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

}

2.2. 主线程代码

头文件

#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 打开失败!");
	}
}

//...


3. 讲解

3.1. 整体程序信号流程

[Qt]自定义信号signals和emit信号_第1张图片

3.2. 信号说明

自定义信号用关键词signals:,类似C++的关键词public、private等用法一致。
如果要自定义保护信号,就在protected:后声明。
自定义信号只需要在头文件的类声明中声明, 然后将连接到信号即可,无需实现信号函数
信号函数槽函数返回值类型任何时候都可以不同,而且如果不关心信号传递下来的参数,信号函数槽函数参数列表也可以不相同, 但是如果要访问信号传递下来的任何参数时, 信号函数槽函数参数列表必须相同

发送信号
只需要用关键字emit后面加上要发的信号,如果要信号函数是有参数的,可以通过形参槽函数传值。

emit openMatlabEngine(m_isOpenMatlabEngine); 
emit openMatlabEngine(true);
emit openMatlabEngine(false); 

3.3. connect说明

// connect函数,最后一个参数需要注意,不能使用默认
connect(m_pThreadMatlab, SIGNAL(openMatlabEngine(bool)), this, SLOT(slot_openMatlabEngine(bool)), Qt::QueuedConnection);

这个参数可以用于线程间的信号传递,详细信息见博文:[Qt]connect()参数Qt:ConnectionType使用讲解


赞赏码New

你可能感兴趣的:(Qt,Qt实用Trick,qt自定义信号,signals,emit,slot)