想了很久,我决定还是先从signal和slot(信号槽)开始讲起。

signal和slot大家一定不陌生,先看一段示例(选自文档):

 class Counter : public QObject
{
Q_OBJECT public:
Counter() { m_value = ; } int value() const { return m_value; } public slots:
void setValue(int value); signals:
void valueChanged(int newValue); private:
int m_value;
};

使用signal和slot的类必须包含Q_OBJECT宏,声明slot需要使用public/private/protected slots:,signal则需要signals:。

这些其实都是宏,它们会指示moc做相应的代码生成,这样Qt程序才可以发送信号,并让slot与signal相连接。

可是golang并没有宏,那么在qt里我们要怎么做呢?

信号----Signal

1. 信号----signal的定义

想要自定义signals,我们需要用到golang的一个简单特性--struct tags。

tags被广泛的用于golang的世界里,从标准库encoding/json到广泛使用的orm(xorm,gorm),tags的身影无处不在。tags之所以应用广泛是因为它可以被reflect取到,

依赖于强大的reflect包,可以通过tags来实现各种各样的功能,其中就包括Qt的moc扩展。

下面我们看一下一个带有两个自定义signal的自定义组件:

 import "github.com/therecipe/qt/core"

 type MyWidget struct {
core.QObject _ func() `signal:"dataChanged"`
_ func(int) `signal:"valueChanged"`
}

首先看到第四行,

core.QObject

所有需要自定义slot和signal的类都必须是core.QObject的派生类型,如果不是直接继承自QObject,那么直接继承的类型必须要直接或间接的继承自QObject。

同时要注意,不要用*core.QObject的形式,这会导致qtmoc忽略这个类,最终不能处理moc扩展引发问题。

_ func() `signal:"dataChanged"`
_ func(int) `signal:"valueChanged"`

我们定义了两个signal,第一个不带任何参数,第二个带有一个int类型参数。

qtmoc会把tags的内容用strings.Title做处理,也就是说dataChanged会变成DataChanged,这就是我们定义的信号的名字。

接着qtmoc会根据这个名字以及tags所在成员的类型生成自定义控件类的三个成员方法:Connect[signal name],Disconnect[signal name],[signal name],

在本例中就是:ConnectDataChanged,DisconnectDataChanged和Datachanged。

2. 信号----signal的连接

想要和signal连接,需要用到前面提到的Connect[signal name]函数。

qtmoc会根据signal的类型来生成Connect函数,这里的ConnectDataChanged的原型就是func ConnectDataChanged( f func() )。

需要连接这个signal时,调用它并把signal处理函数传递为参数即可

func sample() {
fmt.Println("Data has been changed.")
} widget := NewMyWidget(nil) // 这里是创建我们的自定义组件,后面的文章我们会重点讲解
// Qt5中与signal相连的可以是任何函数,在qt里也是一样,所以我们用一个外部函数来处理signal,在实际开发中还是推荐用类的成员方法或者slot进行处理
widget.ConnectDataChanged(sample)

这里我们把sample和信号DataChanged相连,每次触发这个信号时都会打印出“Data has been changed.”这句信息。

如果想要取消和某个信号的连接,需要使用Disconnect[signal name]函数,它不带参数,调用它意味着取消signal与上一次使用Connect[signal name]时作为参数的函数的连接。

widget.DisconnectDataChanged()
// 我们取消了sample函数与DataChanged的连接

3. 信号----signal的触发

在C++中要触发一个信号,只需要如下代码:

emit DataChanged()
emit ValueChanged(value)

emit?在C++和golang里都没见过的语法。。。。。。没错,这也是Qt的moc扩展。

还记得我们说道qtmoc会根据signal tags生成三个成员方法吗,ConnectDataChanged,DisconnectDataChanged,DataChanged

第三个函数就是我们用来触发信号的。

信号触发函数用来代替emit,它自身是一个根据signal tags前的类型生成的函数,所以MyWidget.DataChanged的类型是func f();而ValueChanged函数的类型就是func f(value int)。

注意,与Qt一样,signal不可以拥有返回值。

下面是触发信号的示例:

// 触发DataChanged信号
widget.DataChanged() value :=
// 触发ValueChanged信号并传递参数
widget.ValueChanged()
widget.ValueChanged()
widget.ValueChanged(value)

触发信号之后,之前与之相连的函数就会被调用了。

4. 信号----signal的自动连接

如果自定义的signal比较多,那么一个个的调用Connect[signal name]不仅麻烦低效,还会带来维护上的困难,所以qt提供了自动连接的功能。

先看代码:

import (
"github,com/therecipe/qt/widgets"
) type Auto struct {
widgets.QLabel _ func() `signal:"dataChanged,auto"`
_ func(string) `signal:"valueChanged,auto(this.QLabel.SetText)"`
}

我们看到在signal的名字后面多了一个auto。

这个auto是告诉qtmoc这个信号需要connect一个和signal tags里名字相同的成员方法,在这里成员函数的名字必须和tags里的相同,而不是经过strings.Title处理过的signal名字。

然后我们定义并实现这个和DataChanged连接的成员函数:

func (a *Auto) dataChanged() {
fmt.Println("Data has been changed.")
}

这样你无需再显示调用ConnectDataChanged,DataChanged将自动和成员函数dataChanged连接。

我们还看到有auto(this.QLabel.SetText)的写法,这是在自定义类型继承自其他QObject及其派生类时,可以自动连接基类的成员方法。

this是指当前的对象;

QLabel或是其他类型名表示继承的基类;

SetText是基类的成员函数,它将与DataChanged信号相关联。这里写成setText也可以,因为在()里的函数名会被strings.Title处理。

每当我们触发信号时:

widget := NewAuto(nil, )

widget.DataChanged()
widget.ValueChanged("signal & slot")

相应的成员函数就会被调用,上面的代码会有如下反应:

// 因为DataChanged信号而被触发
widget.dataChanged() // 因为ValueChanged信号而被触发
widget.QLabel.SetText("signal & slot")
// 等价于
widget.SetText("signal & slot")

有人会问,那可不可以用`signal:"dataChanged,auto(this.Myfunc)"`自己指定想要和信号connect的函数呢?

答案是暂时不可以。目前auto只有上面两种用法,不过作者以及把实现自动连接成员变量的成员函数和自定义连接函数加入了开发计划中,相信不久之后就能用上这些功能了。

以上就是qt中signal的具体用法,下一篇我们将会介绍slot的详细用法。

如有疑问欢迎在评论中提出。

参考:

http://doc.qt.io/qt-5/signalsandslots.html

【golang-GUI开发】qt之signal和slot(一)的更多相关文章

  1. 【golang-GUI开发】qt之signal和slot(二)

    上一篇文章里我们详细介绍了signal的用法. 今天我们将介绍slot的使用.在qt中slot和signal十分相像,这次我们将实现一个能显示16进制数字的SpinBox,它继承自QSpinbox并重 ...

  2. qt的signal和slot机制

    signal和slot是QT中的一大特点 signal/slot是Qt对象以及其派生类对象之间的一种高效通信接口 用户可以将N多个信号和单个槽相连接, 或者将将N个槽和单个信号连接, 甚至是一个信号和 ...

  3. 深入了解Qt(三)之元signal和slot

    深入了解Qt主要内容来源于Inside Qt系列,本文做了部分删改,以便于理解.在此向原作者表示感谢! 在Qt 信号和槽函数这篇文章中已经详细地介绍了信号和槽的使用及注意事项.在这里对其使用方面的知识 ...

  4. qt信号signal和槽slot机制

    内容: 一.概述 二.信号 三.槽 四.信号与槽的关联 五.元对象工具 六.程序样例 七.应注意的问题 信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工 ...

  5. Qt Signal and Slot

    Qt4中的信号槽 Qt4中的信号槽是通过SIGNAL,SLOT两个宏,将参数转换成字符串.Qt编译前,会从源码的头文件中提取由signal和slot声明的信号和槽的函数, 将其组成一张信号和槽对应的字 ...

  6. PyQt5 signal and slot

    PyQt5 的 signal 与 slot 有所改变,例如,先定义一个 ZeroSignal 类: class ZeroSignal(QObject): atzero = pyqtSignal(int ...

  7. VS IDE环境下,windows GUI(Qt MFC,win32)使用控制台实时打印调试信息

    在工程属性的页面下,点击Build Events,在Build Events下点击Post-Build Event. 然后再Command Line里面输入以下命令: editbin /SUBSYST ...

  8. Python GUI开发环境的搭建

    原文:Python GUI开发环境的搭建 最近对Python的开发又来了兴趣,对于Python的开发一直停留在一个表面层的认识,玩的部分比较大. Python的入手简单,语法让人爱不释手,在网络通信方 ...

  9. Sublime Text3 + Golang搭建开发环境

    Sublime Text3 + Golang搭建开发环境 http://blog.csdn.net/aqiang912/article/details/46775409 1.安装git 因为golan ...

随机推荐

  1. Object constraint language for code generation from activity models

    一.基本信息 标题:Object Constraint Language for Code Generation from Activity Models 时间:2018 出版源:Informatio ...

  2. Spring-AspectJ 配置文件

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  3. 【Spring】SpringMVC配置文件

    SpringMVC中一般会引入三个配置文件applicationContext.xml.dispatcher-servlet.xml(SpringMVC-servlet.xml).web.xml 1. ...

  4. python 从基础到入门链接

    机器学习篇: 先看的 简书 木子昭的机器学习三剑客 : https://www.jianshu.com/u/c5d047065c42 然后看完之后又发现一个很好的链接, nkwy2012博主提供了很多 ...

  5. python基础自学 第五天(附带视频和相关资源)

    数据类型 01.列表 List 是 python 中使用最频繁的数据类型,在其他语言中叫做数组 专门用于存储一串信息 列表用 [ ] 定义,数据之间用 , 分隔 列表的索引从 0 开始 补:索引就是数 ...

  6. 剑指offer面试题15:链表中倒数第K个节点

    题目:输入一个链表,输出该链表的倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表尾节点是倒数第一个节点. 解题思路: 解法一:一般情况下,单向链表无法从后一个节点获取到它前面的节点,可 ...

  7. 【洛谷3865】 【模板】ST表(猫树)

    传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里

  8. 吴恩达机器学习笔记40-用调和平均数F来进行查准率和查全率之间的权衡(Trading Off Precision and Recall by F sore)

    在很多应用中,我们希望能够保证查准率和查全率的相对平衡. 我们可以将不同阀值情况下,查全率与查准率的关系绘制成图表,曲线的形状根据数据的不同而不同: 我们希望有一个帮助我们选择这个阀值的方法.一种方法 ...

  9. Rpc框架dubbo-client(v2.6.3) 源码阅读(二)

    接上一篇 dubbo-server 之后,再来看一下 dubbo-client 是如何工作的. dubbo提供者服务示例, 其结构是这样的!dubbo://192.168.11.6:20880/com ...

  10. [原创]K8Cscan插件之FTP弱口令扫描

    [原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...