QT入门-UI-信号槽

news2024/10/6 12:30:05

目录

一、QWidget类(重点)

二、子组件(掌握)

三、样式表(熟悉)

一、什么是信号槽?

二、信号槽的连接方式

2.1 自带信号→自带槽

2.2 自带信号→自定义槽

2.3 自定义信号

三、传参方式

3.1 成员变量

3.2 静态局部变量

3.3 信号槽传参

四、对应关系

4.1 一对多

4.2 多对一


一、QWidget类(重点)

QWidget类是Qt中所有可视化组件和窗口的基类,其内部规定了很多成员,这些成员都会继承给其派生类。

常用成员,所有属性的Access functions对应的都是封装后的接口,即getter和setter

  • width : const int

宽度

  • height : const int

高度

宽高无法直接设定,可以通过resize函数一起改变。

  • x : const int

x轴坐标,x轴的正方向向右

  • y : const int

y轴坐标,y轴的正方向向下,原点在左上。

坐标无法直接设定,可以通过move函数一起改变,任何组件和窗口的定位点是左上角。位置是相对的,取决于当前组件或窗口属于什么。

  • void QWidget::show() [slot]

展示

  • void setGeometry(int x, int y, int w, int h)

同时设置坐标与宽高。

二、子组件(掌握)

窗口中要有其它的子组件,不然只是空内容的窗口。

使用QPushButton类作为子组件,QPushButton表示一个按钮,构造函数如下

QPushButton(const QString & text, QWidget * parent = 0)

参数一:显示文本,QString是Qt中的字符串类。

参数二:父窗口或父组件

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入头文件
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    // 改变宽高(不包含标题栏)
    resize(200,200);
    // 移动位置
    move(200,200);
    // 创建按钮对象
    // this指的是主函数中的Dialog w对象
    // this结合多态进行参数传递
    btn = new QPushButton("你好",this);
    btn->resize(50,50);
    // 相对坐标
    btn->move(50,50);
    // 展示
    btn->show();
}

Dialog::~Dialog()
{
    // C++:有new就有delete
    delete btn;
}

三、样式表(熟悉)

默认的组件样式比较普通,可以通过设置样式表来自定义组件样式。

void setStyleSheet(const QString & styleSheet)

参数为QSS语法的样式,QSS语法类似于CSS。

配色网站:在线颜色选择器 | RGB颜色查询对照表

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入头文件
#include <QPushButton>
// 预设样式
#define QPushButton_STYTLE (QString("\
/*按钮普通态*/\
QPushButton\
{\
    font-family:Microsoft Yahei;\
    /*字体大小为20点*/\
    font-size:20pt;\
    /*字体颜色为白色*/\
    color:white;\
    /*背景颜色*/\
    background-color:rgb(188, 238, 104);\
    /*边框圆角半径为8像素*/\
    border-radius:8px;\
}\
/*按钮悬停态*/\
QPushButton:hover\
{\
    /*背景颜色*/\
    background-color:rgb(100 , 137 , 255);\
}\
/*按钮按下态*/\
QPushButton:pressed\
{\
    /*背景颜色*/\
    background-color:rgb(14 , 135 , 10);\
    /*左内边距为3像素,让按下时字向右移动3像素*/\
    padding-left:3px;\
    /*上内边距为3像素,让按下时字向下移动3像素*/\
    padding-top:3px;\
    /*字体颜色为白色*/\
    color:black;\
}"))

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    // 同时设置x,y,宽,高
    setGeometry(200,200,200,200);

    btn = new QPushButton("你好",this);
    btn->setGeometry(50,50,100,100);
    // 给按钮设置样式表
//    btn->setStyleSheet("background-color:green;color:red");
    btn->setStyleSheet(QPushButton_STYTLE);
    // 展示
    btn->show();
}

Dialog::~Dialog()
{
    // C++:有new就有delete
    delete btn;
}

Tip:

在Qt程序运行过程中,如果出现

表示当前程序已经运行,需要先关闭已经运行的程序,再重新运行。

一、什么是信号槽?

之前写的代码,只能看,不能交互。使用信号槽可以让用户与图形用户界面进行人机交互,信号槽是Qt特有的一种组件对象之间的通信机制。

信号函数是一种特殊的函数,槽函数也是一种特殊的函数。

使用信号槽进行组件对象之间的通信有两个前提条件:

1. 通信的对象必须是中QObject派生出来的,QObject类是所有Qt类型的基类。

2. 类中要有Q_OBJECT宏。

信号槽的使用主要通过下面的连接函数:

参数1:发射者,即触发动作的、作为条件的组件对象,通常是名词(对象名称)。

参数2:信号函数的名称,使用SIGNAL()包裹,信号函数是作为条件的动作本身,通常是 动词(函数名称)。信号函数一定属于发射者。

参数3:接收者,作为执行结果动作的对象,通常是名词(对象名称)。

参数4:槽函数的名称,使用SLOT()包裹,作为结果执行的具体动作,通常是动词(函数 名称)。槽函数是一种特殊的成员函数。槽函数一定属于接收者。

整个信号槽的连接,可以总结为:

receiver绑定了sender的signal信号,一旦sender发出signal信号,receiver就执行method函数。

信号槽的断开连接方式有两种:

  • 当发射者或接收者对象销毁时,信号槽连接自动断开
  • 调用disconnect函数手动断开信号槽连接,参数与connect函数一样。

二、信号槽的连接方式

为了方便渐进式的学习,信号槽连接依次讲解以下几种方式:

  • 自带信号→自带槽
  • 自带信号→自定义槽
  • 自定义信号→槽函数(自带或自定义皆可)

2.1 自带信号→自带槽

这是最简单的一种连接方式,因为信号函数与槽函数都是Qt内置的函数,程序员只需要找到对应的关系调用connect函数连接即可。

【例子】点击按钮,关闭窗口。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("关闭",this);
    btn->move(150,150);
    // 连接信号槽
    // 参数1:发射者,按钮
    // 参数2:信号函数,clicked()
    // 参数3:接收者,窗口
    // 参数4:槽函数,close()
    connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}

Dialog::~Dialog()
{
    delete btn;
}

2.2 自带信号→自定义槽

即使Qt内置的函数再多,也总有触及不到的需求,对于一些没有内置的槽函数,就需要程序员手动去编写了。

【例子】点击按钮,窗口向右下方移动 10*根2 个像素,并输出移动后的窗口坐标。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;

    // 1. 声明槽函数
private slots:
    void mySlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("向右下",this);
    btn->move(140,140);
    // 连接信号槽
    // 点击按钮,执行自定义槽函数
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}

// 2. 定义槽函数
/**
 * 窗口向右下方移动14.1个像素,并输出移动后的窗口坐标。
 */
void Dialog::mySlot()
{
    // 获取窗口的当前坐标
    int x = this->x();
    int y = this->y();
    // 移动窗口
    move(x+10,y+10);
    // 打印新坐标
    qDebug() << x+10 << "*" << y+10;
}

Dialog::~Dialog()
{
    delete btn;
}

2.3 自定义信号

这种方式主要用在后面一些特定的时机,现在只是为了讲解强行使用。

信号函数具有以下特点:

  • 信号函数只有声明,没有定义
  • 信号函数无需调用,只需发射
  • 信号函数的参数使用哑元
  • 信号函数无权限

【例子】点击按钮,关闭窗口。

这一次把上面的动作分解为:

点击按钮,调用自定义槽函数,在自定义槽函数中发射自定义信号;

自定义信号触发关闭窗口的动作。

与之前的对比如下:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;

// 声明自定义槽函数
private slots:
    void mySlot();

// 声明自定义信号
signals:
    void mySignal();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(200,200);
    btn = new QPushButton("关闭",this);
    btn->move(80,80);

    // 连接信号槽
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
    connect(this,SIGNAL(mySignal()),this,SLOT(close()));
}

void Dialog::mySlot()
{
    // 发射自定义信号
    emit mySignal();
}

Dialog::~Dialog()
{
    delete btn;
}

三、传参方式

【例子】有一个按钮,按钮上显示按钮点击的次数。

需要用到整型转字符串函数

QString number(int n, int base = 10) [static]

参数1:要转换的数字

参数2:进制

返回值:转换后的字符串

3.1 成员变量

代码与3.2合并。

3.2 静态局部变量

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    int count1 = 0; // 按钮1的点击次数

    QPushButton* btn1;
    QPushButton* btn2;

private slots:
    // 两个按钮点击的槽函数
    void btn1ClickedSlot();
    void btn2ClickedSlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn1 = new QPushButton("0",this);
    btn1->move(150,150);
    btn2 = new QPushButton("0",this);
    btn2->move(150,180);

    // 连接信号槽
    connect(btn1,SIGNAL(clicked()),this,SLOT(btn1ClickedSlot()));
    connect(btn2,SIGNAL(clicked()),this,SLOT(btn2ClickedSlot()));
}

void Dialog::btn1ClickedSlot()
{
    count1++; // 计数+1
    // 把整型转换为字符串
    QString text = QString::number(count1);
    // 设置到按钮上
    btn1->setText(text);
}

void Dialog::btn2ClickedSlot()
{
    static int count2 = 0;
    count2++;
    QString text = QString::number(count2);
    btn2->setText(text);
}

Dialog::~Dialog()
{
    delete btn1;
    delete btn2;
}

3.3 信号槽传参

为了讲解信号槽传参,强行在上面的例子中使用。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;
    int count = 0;

private slots:
    void btnClickedSlot();
    // 带参数的槽函数,来接收信号发送的参数
    void mySlot(int);

signals:
    // 带参数的信号函数
    void mySignal(int);
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("0",this);
    btn->move(50,50);

    connect(btn,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
    connect(this,SIGNAL(mySignal(int)),this,SLOT(mySlot(int)));
}

void Dialog::btnClickedSlot()
{
    count++;
    // 发射带参数的自定义信号
    emit mySignal(count);
}

/**
 * @brief Dialog::mySlot
 * @param count 信号发射过来的
 */
void Dialog::mySlot(int count)
{
    QString text = QString::number(count);
    btn->setText(text);
}

Dialog::~Dialog()
{
    delete btn;
}

信号槽传参需要注意:

1. 理论上可以传递任意多个参数,但通常传递1-2个参数。

2. 信号的参数个数必须大于等于槽的参数个数。

3. 参数的类型需要一一匹配。

四、对应关系

4.1 一对多

同一个信号可以同时链接到多个槽。

一对多的情况也可以优化为下面的代码:

4.2 多对一

多个信号也可以同时连接到同一个槽。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn1;
    QPushButton* btn2;

private slots:
    void mySlot1();
    void mySlot2();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(200,200);
    btn1 = new QPushButton("按钮1",this);
    btn2 = new QPushButton("按钮2",this);
    btn1->move(50,50);
    btn2->move(50,80);
    // 一对多
    //    connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot1()));
    //    connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot2()));
    // 多对一
    connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot1()));
    connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot1()));
}

void Dialog::mySlot1()
{
    qDebug() << "槽函数1";
}

void Dialog::mySlot2()
{
    qDebug() << "槽函数2";
}

Dialog::~Dialog()
{
    delete btn1;
    delete btn2;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#语言实例源码系列-伪装文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

Redis分布式锁存在的问题

假设有这样一个场景&#xff0c;在一个购票软件上买一张票&#xff0c;但是此时剩余票数只有一张或几张&#xff0c;这个时候有几十个人都在同时使用这个软件购票。在不考虑任何影响下&#xff0c;正常的逻辑是首先判断当前是否还有剩余的票&#xff0c;如果有&#xff0c;那么…

Spring5.3.0源码下载

目录源码下载环境配置import into idea修改配置gradle-wapper.propertiesbuild.gradleSetting Gradlerefresh Gradle写一个小dome源码研究心得源码下载 Spring5.3.0 Download Address 我们只需要下载zip就行了&#xff0c; 如果忘记了这个地址&#xff0c;可以在Spring Offici…

网络技术——网络运维工程师必会的网络知识(3)(详细讲解)

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.网络层协议与应用 1.网络层的功能 2.IP数据包格式 3.广播与…

100天精通Python(数据分析篇)——第70天:Pandas常用排序、排名方法(sort_index、sort_values、rank)

文章目录每篇前言一、按索引排序&#xff1a;sort_index()1. Series类型排序1&#xff09;升序2&#xff09;降序2. DataFrame类型排序1&#xff09;按行索引排序2&#xff09;按列索引排序二、按值排序&#xff1a;sort_values()1. Series类型排序1&#xff09;升序2&#xff…

冻结集合:不可能增删frozenset()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 冻结集合&#xff1a;不可能增删 frozenset() 选择题 对于以下python代码表述错误的一项是? a{1,2} print("【显示】a",a) a.add(3) print("【执行】a.add(3)【显示】a"…

【现代机器人学】学习笔记七:开链动力学(前向动力学Forward dynamics 与逆动力学Inverse dynamics)

这节的内容主要讲述机器人动力学的内容。相对于本书其他部分运动学内容相比&#xff0c;把动力学一下子合成了一章。看完以后有三个感受&#xff1a; 1.本章难度相对其他章节较大&#xff0c;因此需要反复去看&#xff0c;以求对重要内容的眼熟&#xff0c;不求全部记住&#…

Java window多环境配置

目录JDK版本下载配置内容描述创建JAVA_HOME在Path配置版本切换效果JDK版本下载 Java8 Download address 这个是Java8 的下载地址&#xff0c;下载是要登录的&#xff0c;自己花费一点时间去注册。如果想要下载其它版本的JDK&#xff0c;请看下面的图&#xff0c;然后你就可以看…

QT数据库-网络编程-打包

目录 一、讲解之前 二、数据库基本操作 三、模糊查询 二、编程之前 三、通信结构 一、设置应用图标&#xff08;熟悉&#xff09; 二、Debug和Release模式&#xff08;掌握&#xff09; 三、动态链接库&#xff08;掌握&#xff09; 四、打包&#xff08;熟悉&#xff09; 一、…

FastDDS(10)Transport Layer传输层

传输层在DDS实体之间提供通信服务,负责通过物理传输实际发送和接收消息。DDS层将此服务用于用户数据和发现流量通信。然而,DDS层本身是独立于传输的,它定义了一个传输API,可以运行在实现该API的任何传输插件上。这样,它就不局限于特定的传输,应用程序可以选择最适合其需求…

公众号开发(4) —— 使用Senparc.Weixin SDK进行模板消息推送

微信公众号支持推送模板消息给特定用户&#xff0c;只要获取到公众号用户的openid向微信提供的接口发送post请求即可向特定用户推送模板消息&#xff0c;以下记录简单记录使用Senparc.Weixin SDK进行模板消息推送的过程。 1 模板消息建立 在微信公众号测试账号中添加如下消息…

数据结构之排序【冒泡排序和快速排序之一的实现及分析】内含动态演示图

引言&#xff1a; 今天分享一下一点小事迹&#xff0c;自从从学校回到家里&#xff0c;我已经好久没睡上一个好觉了&#xff0c;因为真的冷&#xff0c;莫名被窝总是感觉很冷&#xff0c;然后穿着袜袜的脚也是冰凉&#xff0c;所以每次早晨要起床的时候总是感觉非常的冷&#…

shell基础使用

一、hello world 首先建立一个tmux vim test.sh //再创建一个test.sh文件 进入文件后&#xff0c;创建一个如下命令&#xff0c;指明bash为脚本解释器 #! /bin/bash //相当与c头文件echo "hello world"运行方式 1.作为可执行文件 acs9e0ebfcd82d7:~$ chmod x test.s…

我是如何将2千万StackOverflow问答翻译成中文的?

大家好&#xff01;大家觉得如果需要翻译SO上全部问答可以怎么做呢&#xff1f;我讲讲我是怎么的&#xff0c;大家看看做得怎么样。 自我介绍 我是一名有10年开发经验的老程序员。做过大数据&#xff0c;做过Java程序员&#xff0c;也做过算法工程师&#xff0c;目前是一名大厂…

Spring Security的项目中集成JWT Token令牌安全访问后台API

Spring Security的项目中集成JWT Token令牌安全访问后台API引言JWT 简介jwt token 的适用场景jwt 的结构完整jwtjwt 的使用方式客户端获取jwt令牌访问受保护资源的具体流程Spring Security 安全框架下使用jwt token新建一个spring boot项目加入spring security 和 jwt 相关依赖…

五、传输层(二)UDP

目录 2.1 UDP概述 2.2 UDP的首部格式 2.3 UDP校验 2.1 UDP概述 UDP无须建立连接。因此不会引入建立连接的时延。 UDP为无连接状态。因此当服务器使用UDP时&#xff0c;一般能支持更多的活动客户机。 UDP分组首部仅有8B的开销&#xff0c;而TCP有20B的首部开销。 应用层…

后端思维篇:如何抽个上报模板

前言 大家好&#xff0c;我是田螺。 我的后端思维专栏好久没更新啦&#xff0c;本文是后端思维专栏的第六篇哈。我的整个后端思维专栏都是跟日常工作相关的哈。 最近刚好优化了安全上报这块的代码&#xff0c;抽了一个基础模板&#xff0c;看起来挺优雅的。所以今天手把手教…

〖产品思维训练白宝书 - 产品思维认知篇⑤〗- 学习 [产品思维] 需要做哪些准备?

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…

php wampserver的使用配置

php wampserver的使用配置wampserver1.php时区配置2.修改apache服务器端口号3.设置起始页4.设置web服务器主目录5.设置虚拟目录wampserver WampServer是Windows Apache Mysql PHP集成安装环境&#xff0c;在Windows操作系统下的apache、php和mysql的服务器软件。 1.php时区配…

RabbitMQ 第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第二天 高级7 RabbitMQ 高级特性7.2 Consumer Ack7.2.1 Consumer Ack7.2.2 Consumer Ack 小结7.2.3 消息可靠性总结第二天 高级 7 RabbitMQ 高级特性 7.2 Consumer Ack 7.2.…