一、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特有的一种组件对象之间的通信机制。
信号函数是一种特殊的函数,槽函数也是一种特殊的函数。
使用信号槽进行组件对象之间的通信有两个前提条件:
通信的对象必须是中QObject派生出来的,QObject类是所有Qt类型的基类。
类中要有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-2个参数。
信号的参数个数必须大于等于槽的参数个数。
参数的类型需要一一匹配。
四、对应关系
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;}
版权归原作者 樱桃的崩崩 所有, 如有侵权,请联系我们删除。