0


QT入门-UI-信号槽

一、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_OBJECTpublic:    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_OBJECTpublic:    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_OBJECTpublic:    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_OBJECTpublic:    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_OBJECTpublic:    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_OBJECTpublic:    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_OBJECTpublic:    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_OBJECTpublic:    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;}
标签: qt c++ 开发语言

本文转载自: https://blog.csdn.net/m0_68210771/article/details/128437594
版权归原作者 樱桃的崩崩 所有, 如有侵权,请联系我们删除。

“QT入门-UI-信号槽”的评论:

还没有评论