QT信号槽详解

摘要:
}信号和插槽功能通过连接功能连接;对于SIGNAL和SLOT模式,必须添加参数:无法确定连接的插槽功能;connect(ui.verticalScrollBarAlarm:SLOT(AlarmListVScrool(int)));需要带参数的连接方法:否则,无法确定插槽功能;
1         QT信号槽详解

1.1  信号和槽的定义

信号是触发信号,例如按钮的点击触发一个clicked信号,槽是用来接收信号,并处理信号,相当于信号响应函数。一个信号可以关联多个槽函数,信号也可以连接信号。

要使用信号槽,类必须继承与QObject类或者其子类,否则无法识别槽函数错误。在类的定义开头需要添加宏定义Q_OBJECT。如下

class AlarmCenter : public QWidget

{

       Q_OBJECT

//用关键字signals定义信号,关键字slots定义槽函数。如下所示:

public slots:

              void SlotHideNoPlatPalyerTip(int tip);

signals:

       void signalHideNoPlatPalyerTip (int tip);

}

信号和槽函数之间采用connect函数进行连接,采用disconnect函数取消连接。在需要触发信号的地方,采用关键字emit signalHideNoPlatPalyerTip (3);触发信号,调用槽函数,传入参数。

1.2  信号槽的连接方式

1.2.1            按照名称自动关联

自动关联需要响应函数的名称按照格式 on_按钮的名称_信号名称()来书写,并将该函数声明为槽slots。点击按钮的时候就会自动关联该信号到该响应函数。

头文件中:

public slots:

void on_BtnStart_clicked();

源文件中:

void AlarmCenter::on_BtnStart_clicked()

{

       int i = 0;

}

1.2.2            Connect连接信号与槽函数

(1)无参数信号槽函数连接

&获取指针需要指定类名称,用宏定义SIGNAL和SLOT可以直接指定函数名称。

QObject::connect(ui.fliterBtn, &QToolButton::clicked, this, &AlarmCenter::DisplayFliterWidget);

       connect(ui.fliterBtn, SIGNAL(clicked()), this, SLOT(DisplayFliterWidget ()));

(2)有参数信号槽函数连接

signals:

void valueChanged(int value);

slots:

void AlarmCenter::AlarmListVScrool(int position);

&方式无需添加参数,SIGNAL和SLOT方式则要添加参数,注意使用&方式时,如果槽函数是重载函数,则编译出错,因为没有参数,无法判断是连接哪个槽函数,所以建议采用,SIGNAL和SLOT方式带上参数。多个参数用逗号隔开,只添加形参类型,不加形参实体。

QObject::connect(ui.verticalScrollBarAlarm, &QScrollBar::valueChanged, this, &AlarmCenter::AlarmListVScrool);

QObject::connect(ui.verticalScrollBarAlarm, SIGNAL(valueChanged(int)), this, SLOT(AlarmListVScrool(int)));

对于有重载函数的槽函数,需要用到有参数的连接方式,否则无法判断是哪个槽函数。

(3)自定义结构体参数的信号槽连接

       对于自定义的结构体参数,信号槽无法识别参数,导致信号槽连接不起作用。所以需要注册结构体参数。在结构体中声明结束的地方加上结构体注册。

struct DealDetailInfo

{

};

Q_DECLARE_METATYPE(DealDetailInfo);

信号定义

signals:

    void signalOnePointUpdateData(QVariant VarDetailInfo);

槽函数定义

void SlotOnePointUpdateData(QVariant VarDealInfo);

信号槽连接

QObject::connect(&m_DealDetail, SIGNAL(signalOnePointUpdateData(QVariant)), this, SLOT(SlotOnePointUpdateData(QVariant)), Qt::QueuedConnection);

 

发送信号的地方用变量QVariant包装结构体参数

QVariant DataVar;

DataVar.setValue(DetailInfo);

emit signalOnePointUpdateData(DataVar);

接收信号的地方从包装中取出结构体参数

DealDetailInfo DealInfo;

DealInfo= VarDealInfo.value<DealDetailInfo>();

1.2.3            信号与信号连接

当存在复杂的包含关系时,A是B的成员对象,B是C的成员对象。在A中触发的信号需要C中的槽函数响应,则需要连接A中的信号触发B中的信号,B中的信号触发C中的槽函数。例子如下:

Class A

{

 signals:

  signalChangeColor(int i);

}

Class B

{

       signals:

  signalChangeColor(int i);

privite:

A a;

}

QObject::connect(&a,SIGNAL(signalChangeColor(int)), this, SIGNAL(signalChangeColor(int)));

Class C

{

       public lots:

SlotChangeColor(int i)

privite:

B b;

}

QObject::connect(&b,SIGNAL(signalChangeColor(int)),this, SLOT(SlotChangeColor(int i)));

1.2.4            信号和lambda表达式连接

当槽函数比较简单,没有必要创建一个槽函数去连接,可以直接用一段简短的代码作为信号接收处理。日下所示。

QObject::connect(ui.closeDisPlayImageWndBtn, &QToolButton::clicked, this, [=]()

       {

              m_imageWidth = 0;

              m_imageHeight = 0;

              m_iPercent = 100;

              m_izoomLevel = 0;

close();

       });

或者控件是new出来的,需要关联控件信号到函数

QCheckBox *CheckBox = new QCheckBox(ui.tableWidget);

QSize size(39, 35);

CheckBox->setFixedSize(size);

CheckBox->setCheckState(Qt::Unchecked);

QObject::connect(CheckBox, &QCheckBox::clicked,this, [=]()

{

       AlarmTableItemChoosed(step, 0);//成员函数

});

1.2.5            QT Designer界面上连接信号槽

       进入QT Designer 界面,点击信号槽编辑按钮,进入信号槽编辑界面,拖动按钮,对按钮的信号槽进行编辑,可以选用已有的槽,或者点击编辑按钮,新增自定义槽。关联之后,在ui_*.h(*表示对话框类名)中会自动添加一行,QObject::connect(BtnStart, SIGNAL(clicked()), AlarmCenterClass, SLOT(sbclslot()));然后在dialog类的文件中实现该槽。

QT信号槽详解第1张

                       

1.3  信号槽的连接响应类型

连接信号与槽的connect()函数原型如下:

bool QObject::connect ( const QObject * sender, const QMetaMethod & signal, const QObject * receiver, const QMetaMethod & method, Qt::ConnectionType type = Qt::AutoConnection );

       最后一个参数Qt::ConnectionType是连接类型,不同的连接类型,槽函数的响应策略如下:

Constant

Value

Description

Qt::AutoConnection

0                                                        

自动识别。当信号发送者和接收者处于同一线程内时,这个类型等同于DirectConnection,反之等同于QueuedConnection,这个类型也是connect函数的默认连接类型

Qt::DirectConnection

1

同步执行。信号一旦发射,与之关联的槽函数立即执行,执行返回后才能执行emit之后的代码,相当于函数调用。

Qt::QueuedConnection

2

异步执行。当信号产生,信号会暂时被缓冲到一个消息队列中,不用等待槽函数返回,就会执行后面的代码。等待接收者的事件循环处理去队列中获取消息,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作

Qt::BlockingQueuedConnection                                                                                                                                                

3

阻塞执行。这种类型类似于QueuedConnection,但是它只能应用于跨线程操作即发送者和接收者处于不同的线程中的情况,并且信号发送者线程会阻塞等待接收者的槽函数执行结束。如果是同一个线程调用,会造成死锁现象。

Qt:: Unique   Connection

0x80

作用相当于Qt::AutoConnection。只是防止重复连接。如果当前信号和槽已经连接过了,就不再连接了。

1.4  一个信号多个槽函数的调用顺序

存在一个信号连接多个槽函数的情况,槽函数的调用顺序与连接的先后一致,但这只适用于同步调用,异步调用是加入到信号队列中,无法判断调用先后顺序。

1.5  带返回值的信号

大都说Qt信号槽不能使用返回值。Qt5中,信号槽是有返回值的。只是Qt的一个信号可以连接多个槽,还有同步调用和异步调用的问题,没发支持的很好,所以,返回值虽有,但只是鸡肋。同步调用才有返回值,异步调用的返回值永远为返回值类型默认构造函数出来的。连接的多个槽都返回值,那么结果是最后调用(连接)的那个。也就是说对于QueuedConnection连接的信号槽,永远只是返回返回类型的默认构造函数的。对于AutoConnection连接的,如果发出信号的线程和槽函数线程不同亦然。所以只有同步调用或者阻塞调用,才会成功返回值。

bool bReturn; 

QMetaObject::invokeMethod(&object, "signalname", Qt::DirectConnection/* Qt::BlockingQueuedConnection */, Q_RETURN_ARG(bool, bReturn), Q_ARG(int, i));  

自己编了一个股票监控软件,有如下功能,有兴趣的朋友可以下载;

(1)   个股监测。监测个股实时变化,可以监测个股大单交易、急速拉升和下降、主力入场和出场、股票最高点和最低点提醒。检测到最高点、最低点、主力进场点、主力退场点、急速拉升点、急速下跌点,给出语音或者声音提醒,不用再时刻看着大盘了,给你更多自由的时间;

(2)   大盘监测。监测大盘的走势,采用上证、深证、创业三大指数的综合指数作为大盘走势。并实时监测大盘的最高点和最低点、中间的转折点。

(3)   股票推荐。还能根据历史数据长期或短期走势进行分析,对股市3千多个股票进行分析对比,选出涨势良好的股票,按照增长速度从大到小排序,推荐给你涨势良好的股票;

下载地址:

1.0.3版本(修复大盘指数崩溃缺陷)下载地址:

链接:https://pan.baidu.com/s/1BJcTp-kdniM7VE9K5Kd3vg 提取码:003h

更新链接:

https://www.cnblogs.com/bclshuai/p/10621613.html

                       

免责声明:文章转载自《QT信号槽详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Piwik学习 -- 插件开发Linux下常用redis指令下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android插件实例——360 DroidPlugin具体解释

在中国找到钱不难,但你的一个点子不意味着是一个创业。你谈一个再好的想法,比方我今天谈一个创意说,新浪为什么不收购GOOGLE呢?这个创意非常好。新浪一收购GOOGLE。是不是新浪就变成老大了?你从哪儿弄来钱?怎么去整合GOOGLE呢; 之前写过有关于Android 插件方向的文章,解析了一下Android的插件原理与执行方式。非常多小伙伴都问我。为...

c# 判断窗体是否永在最前(TopMost),调用windows API

  许多程序都可以把自身的窗体设为最前显示状态,这个可以参考博客c#让窗体永在最前 调用windows api 将窗体设为topmost。那么如何判断桌面上的一个窗体是否为最前显示状态呢,不光是自己的程序,还包括其它程序。我们可以通过调用Windows Api的GetWindowLong方法判断。   GetWindowLong是一个Windows API...

CentOS7安装桌面环境 并支持远程访问

最近要在CentOS环境下装IDE,之前的CentOS都是做服务器用,都是最小安装,没有桌面环境,因此需要……搞快点! 1、安装所需软件 yum install -y epel-release yum install -y lightdm yum groups mark convert "X Window system" yum groups mark...

easyui treegrid 动态展开数据(暂记)

 ClassifyAdminSynMsgSvr.GetCLFLList("<%=CurUTag %>", 1, "", function (ret) {                    //console.log(ret);                    //console.log(ret._Items);            ...

MarkDownPad2基本语法

一、换行和空格  (1)换行   行尾加两个空格   (2)空格   &nbsp;   二、标题  在#后跟个空格再写文字,一个#是一级标题,两个#是二级标题,以此类推,支持六级标题。   示例: # 一级标题 ## 二级标题 ### 三级标题 显示效果:   三、字体  (1)加粗   要加粗的文字左右分别用两个*号包起来。 示例:   **这是...

MFC中Carray的使用

CArray   需要包含的头文件 <afxtempl.h>   CArray类支持与C arrays相似的数组,但是必要时可以动态压缩并扩展。数组索引从0开始。可以决定是固定数组上界还是允许当添加元素时扩展当前的边界。内存对上界是连续地分配空间,甚至一些元素可为空。   和C arrays一样,CArray索引元素的访问时间是不变的,与数组大...