【QT(三)】—— 信号和槽

前言

简单了解了Qt,现在来学习Qt中的 信号和槽

信号和槽

在 Qt 当中,用户和控件的每一次交互过程称为一个事件;例如:用户点击按钮、用户关闭窗口。这些事件都会发出一个信号

Qt中所有的控件都具有接受信号的能力,并且一个控件还可以接受多个不同的信号。对于接收到的每个信号,控件就会做出相应的动作。

对于接受到的信号,所做出的相应动作,就是 (槽函数)

在Qt中,事件 是用户与控件的交互行为(如点击按钮、输入文本),而控件在事件发生后会发出信号 是响应信号的函数------信号是"通知",槽是"动作",二者通过connect绑定,实现"事件触发→信号发送→槽函数执行"的逻辑链。

信号和槽,是Qt特有的消息传输机制,能将相互独立的控件关联起来。

例如:点击按钮,没有任何反应;就可以对cdicked信号,设置对应的槽函数,这样在点击时就会做出相对应的动作。

connect 的使用

在之前,我们只是创建出来一个控件(文本、按钮等),实际运行起来,点击按钮是没有任何反应的。

那是因为我们并没有对该控件产生的信号关联槽函数,也就是没有对该控件产生的信号做处理。

要将控件产生的信号关联槽函数就要使用connect

对于connect函数,包含4个需要传递的参数:

  • sender:表示产生信号的控件(谁产生的信号)
  • signal:表示产生的什么信号(产生的什么信号)
  • receiver:表示信号的接受方(谁处理这个信号)
  • method:表示信号的处理方法(如何处理这个信号)

这里创建一个按钮,对该按钮产生的clicked信号(按下)关联槽函数(Widget::close)关闭窗口

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton(this);
    button->move(200,200);
    connect(button,&QPushButton::clicked,this,&Widget::close);
}

这样,在按下按钮时,整个程序窗口就会被关闭。

自定义槽函数

上述关联的槽函数是Widget::close,是Qt内置的槽函数;

当然,我们也可以自己实现一个槽函数,并于某个控件产生的信号关联。

例如,这里自定义一个槽函数,实现按下按钮,使得按钮上的文字在hello qthello world直接切换

cpp 复制代码
//在Widget.h在声明
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void handle();
private:
    Ui::Widget *ui;
};
//在Widget.cpp中定义
void Widget::handle()
{
    if(ui->pushButton->text() == "hello qt")
            ui->pushButton->setText("hello world");
    else
        ui->pushButton->setText("hello qt");
}
//在Widget构造函数中关联槽函数
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handle);
}

这样,就对于创建的按钮产生的clicked信号关联了自定义槽函数。

无论是使用代码创建QPushButto对象,还是通过form图形化界面创建的按钮都可以使用connect关联槽函数。

自定义槽函数 ,需要在声明时带上public slots字段。(Qt 5以后版本也可以不用带该字段)

自定义信号

在Qt当中,内置了非常多的信号和槽函数,这样内置的信号槽可以满足大部分的开发需求。

我们也可以自定义信号,并且对于自定义的信号关联槽函数。

自定义信号,需要带上signals:字段(Qt 5 以后版本可以不用带该字段)

自定义信号只需声明,无需定义

cpp 复制代码
//Widget.h
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void mysignal();
private:
    Ui::Widget *ui;
};

自定义信号,也可以关联槽函数(内置和自定义槽函数都可以)

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(this,&Widget::mysignal,this,&Widget::close);
}

到这里,我们会发现:自定义了信号,关联了槽函数;

但是没有触发信号啊,运行起来没有任何反应啊

触发信号

对于内置信号,例如clicked,用户按下按钮就会触发;

而自定义信号,用户操作不会触发我们自定义的信号,就需要我们手动触发。

触发信号的关键字emit(Qt 5 以后版本也可以省略该字段)

cpp 复制代码
emit mysignal();

到这里,我们会发现:所谓的信号和槽,不就是类中的不同函数吗。

参数问题

对于自定义信号和槽,可以给其设定参数。

对于带参数的信号,在关联槽函数时就要注意:

  • 参数类型必须相同。
  • 参数个数可以不同,信号的参数个数必须大于或等于槽函数的参数个数。

form自动生成槽函数

我们可以使用form创建控件,当然也可以使用form来生成对应的槽函数。

这样就可以自动生成对应槽函数的声明和定义

通过这种方式创建的槽函数是不需要调用connect关联的

这种方式生成的槽函数,命名是有规律的:on_objectName_signal

objectName:创建控件时,控件属性objectName对应的值

signal:所关联的信号名称

disconnect取消关联

connect可以关联槽函数,而distconnect就取消信号和槽函数的关联。

disconnect的用法和connect一样,需要传递4个参数。

其常用在取消关联某一个槽函数,转而关联另外一个槽函数。

lambda 简化槽函数

C++11中,存在lambda表达式,这里在调用connect,传递槽函数时,就可以使用lambda来充当槽函数。

对于Qt 5 以后的版本,默认按照 C++ 11来进行编译的;而对于旧版本,就需要在.pro文件中加上C++11的编译选项。

相关推荐
We་ct44 分钟前
深度剖析浏览器跨域问题
开发语言·前端·浏览器·跨域·cors·同源·浏览器跨域
skywalk81631 小时前
在考虑双轨制,即在中文语法的基础上,加上数学公式的支持,这样像很多计算将更加简单方便,就像现在的小学数学课本里面一样,比如:定x=2*x + 1
开发语言
小书房1 小时前
Kotlin的by
android·开发语言·kotlin·委托·by
就叫飞六吧1 小时前
QT写一个桌面程序exe并动态打包基本流程(c++)
开发语言·c++
threelab1 小时前
Three.js 代码云效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
V搜xhliang02462 小时前
OpenClaw科研全场景用法:从文献到实验室的完整自动化方案
运维·开发语言·人工智能·python·算法·microsoft·自动化
kaikaile19952 小时前
风、浪、流环境模型的船舶三自由度(纵荡、横荡、艏摇)运动仿真MATLAB
开发语言·人工智能·matlab
fish_xk2 小时前
map和set
java·开发语言
李崧正2 小时前
Java技术分享:Lambda表达式与函数式编程
java·开发语言·python
老了,不知天命2 小时前
鳶尾花項目JAVA
java·开发语言·机器学习