目录
案例:计算圆面积(两种方式实现)
方式一:设计器 Qt Designer实现 (20201015)
方案A:触发按钮事件(_clicked())
方案B:触发输入编辑框事件(_textChanged(const Qstring &arg1))
方式二:代码实现(202010152)
方案A:触发按钮事件
方案B:触发输入编辑框事件
信号和槽机制:任意两个Qt对象之间的通信机制(使对象间灵活通信)
1.信号与槽机制的连接方式
2.信号与槽机制的优点
3.信号与槽机制的缺点
Qt元对象系统:是标准C++的扩展,但不支持C++模板
Qt是一个跨平台的C++形用户界面应用程序框架,我们用Qt进行GUI应用程序开发。
GUI:图形用户界面。
Qt开发应用程序的方式有两种:(1)Qt的GUI界面设计器 (Qt Designer);(2)手写代码。
这两种的区别在于创建新项目过程中有无勾选“创建界面”选项,如下图所示:
案例:计算圆面积(两种方式实现)
计算圆的面积:S=π×(r^2) (半径/面积)
方式一:设计器 Qt Designer实现 (20201015)
设计区窗体部分:
Edit Widgets (F3) 编辑控件
Edit Signals/Slots (F4) 编辑信号/槽
Edit Buddies 编辑伙伴(QLabel标签关联快捷键)
Edit Tab Order 编辑Tab顺序
水平布局 (H)
垂直布局 (V)
使用分裂器水平布局 (P)
使用分裂器垂直布局 (L)
在窗体布局中布局 (F)
栅格布局 (G)
打破布局 (B)
调整大小 (S)
QLabel属性没有设置之前,QFrame下的frameShape为NoFrame,frameShadow为Plain,我们根据需要分别设置frameShape为Panel,frameShadow为Sunken。
改变QLabel属性之后的对比如下(可以看到下沉效果的盘子 Sunken/Panel):
int main( )函数是应用程序的入口。
几乎所有使用Qt的情况下,main()函数只需在将控制转交给Qt库之前执行初始化,然后Qt库通过事件向程序告知用户的行为。
【main.cpp】
#include "dialog.h" //使用哪个类就必须把包含该类的头文件引用过来(*.h文件中包含了相应类的定义)
#include <QApplication> //每个使用[Qt图形化应用程序]中都必须使用一个QApplication对象
//QApplication管理各种各样的图形化应用程序的广泛资源、基本设置、控制流及事件处理等
int main(int argc, char *argv[]) //这里是应用程序的入口。几乎所有使用Qt的情况下,main()函数只需在将控制转交给Qt库之前执行初始化,然后Qt库通过事件向程序告知用户的行为。
//所有Qt程序必须有且只有一个main()函数。argc是命令行变量的数量,argv是命令行变量的数组。
{
QApplication a(argc, argv); // a是创建的QApplication类的对象,用来处理命令行变量。所有被Qt识别的命令行参数都将从argv中移去,argc也因此减少
Dialog w; //创建对话框Dialog类的对象(包含该类头文件)
w.show(); //窗口部件可见
return a.exec(); //main()函数将控制权交给Qt,Qt完成事件处理工作,当应用程序退出的时候,exec()函数的值就会返回。
//exec()函数中,Qt接收并处理用户和系统的事件,并且将他们传递给适当的窗口部件。
}
方案A:触发按钮事件(_clicked())
即文本框内输入数值,点击“计算”按钮,得出计算结果
【dialog.cpp】
#include "dialog.h"
#include "ui_dialog.h"
const static double PI=3.1416; //静态全局变量PI
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_countBtn_clicked()
{
bool ok; //为什么用这个呢???
QString tempStr; //临时变量
QString radiusStr = ui->radiuslineEdit->text(); //半径(字符串类型变量) //控件属性需设置:只许输入数字,不许输入汉字
int radiusValue = radiusStr.toInt(&ok); //半径(整型变量)
double area = radiusValue*radiusValue*PI; //面积(S=pi*r^2)
ui->arealabel_2->setText(tempStr.setNum(area));//整型变字符串,计算结果显示
}
方案B:触发输入编辑框事件(_textChanged(const Qstring &arg1))
即文本框内输入数值,不需单击按钮,直接显示计算结果
【dialog.cpp】
#include "dialog.h"
#include "ui_dialog.h"
const static double PI=3.1416; //静态全局变量PI
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_radiuslineEdit_textChanged(const QString &arg1)
{
bool ok; //为什么用这个呢???
QString tempStr; //临时变量
QString radiusStr = ui->radiuslineEdit->text(); //半径(字符串类型变量) //控件属性需设置:只许输入数字,不许输入汉字
int radiusValue = radiusStr.toInt(&ok); //半径(整型变量)
double area = radiusValue*radiusValue*PI; //面积(S=pi*r^2)
ui->arealabel_2->setText(tempStr.setNum(area));//整型变字符串,计算结果显示
}
方式二:代码实现(202010152)
方案A:触发按钮事件
【dialog.h】
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
//class类:默认是私有变量;struct类:默认是公用变量。
class Dialog : public QDialog
{
Q_OBJECT //Q_OBJECT是个宏。作用是启动Qt5元对象系统的一些特性(如支持信号和槽等)。它必须放在类定义的私有区中。
public:
Dialog(QWidget *parent = 0); //构造函数
~Dialog(); //析构函数
private:
QLabel *label1,*label2; //声明QLabel类控件的对象
QLineEdit *lineEdit; //声明QLineEdit类控件的对象
QPushButton *button; //声明QPushButton类控件的对象
private slots:
void showArea(); //声明槽函数
};
#endif // DIALOG_H
【dialog.cpp】
#include "dialog.h"
#include <QGridLayout> //布局管理器
const static double PI=3.1416; //静态全局变量
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
label1 = new QLabel(this); //创建QLabel类的对象1
label1->setText(tr("请输入圆的半径:"));
lineEdit = new QLineEdit(this); //创建QLineEdit类的对象
label2 = new QLabel(this); //创建QLabel类的对象2
button = new QPushButton(this); //创建QPushButton类的对象
button->setText(tr("显示圆的面积"));
QGridLayout *mainLayout = new QGridLayout(this); //4个控件的布局管理
mainLayout->addWidget(label1,0,0);
mainLayout->addWidget(lineEdit,0,1);
mainLayout->addWidget(label2,1,0);
mainLayout->addWidget(button,1,1);
//信号和槽的关联
connect(button,SIGNAL(clicked()),this,SLOT(showArea())); //方式A:触发按钮事件
//connect(lineEdit,SIGNAL(textChanged(QString)),this,SLOT(showArea())); //方式B:触发输入编辑框事件
}
Dialog::~Dialog()
{
}
//定义槽函数
void Dialog::showArea()
{
bool ok; //为什么用这个呢???
QString tempStr; //临时变量--字符串型
QString radiusStr = lineEdit->text(); //半径(字符串类型变量) //控件属性需设置:只许输入数字,不许输入汉字
int radiusValue = radiusStr.toInt(&ok); //半径(整型变量)
double area = radiusValue*radiusValue*PI;//面积(S=pi*r^2)
label2->setText(tempStr.setNum(area)); //整型变字符串,计算结果显示
}
方案B:触发输入编辑框事件
connect(lineEdit,SIGNAL(textChanged(QString)),this,SLOT(showArea())); //方式B:触发输入编辑框事件
附录:
信号和槽机制:任意两个Qt对象之间的通信机制(使对象间灵活通信)
1.信号与槽机制的连接方式
( 0 )常用:一个信号和一个槽相连
( 1 )一个信号和另一个信号相连
( 2 )一个信号和多个槽相连
( 3 )一个槽响应多个信号
2.信号与槽机制的优点
1)类型安全。需要关联的信号和槽的签名等同 —— 即:信号的参数类型和个数与接收该信号的槽的参数类型和个数相同。
2)松散耦合。 Qt 对象的耦合度很低。激发信号的 Qt 对象只需在适当时间发送适当信号,不需要知道哪个对象的哪个槽接收它发出的信号,不需要关心它发出的信号有没有被接收到,更不需要知道哪个对象的哪个槽接收到了该信号。同样,对象的槽也不知道被哪些信号关联了。
3.信号与槽机制的缺点
同回调函数相比,信号与槽机制的运行速度有些慢。通常通过传递一个信号来调用槽函数会比直接调用非虚函数的运行速度慢 10 倍。主要原因如下:
( 1 )需要定位 接收信号的对象
( 2 )安全地遍历所有的关联(如一个信号关联多个槽)
( 3 )编组 / 解组传递的参数( marshal/unmarshal )
( 4 )在多线程时,信号可能需要排队等待
Qt元对象系统:是标准C++的扩展,但不支持C++模板
—— 提供对象间的通信机制(信号和槽)、运行时类型信息和动态属性系统的支持,使 Qt 能更好地实现 GUI 图形用户界面 编程。
Qt 元对象系统基于以下三个事实:
( 1 )基类 QObject :任何需要使用元对象系统功能的类,必须继承自 QObject 。
( 2 ) Q_OBJECT 宏:用于启动元对象的特性,必须出现在类的私有声明区中。
( 3 )元对象编译器( moc, Meta-Object ):为 QObject 子类实现 元对象特性 提供必要的代码实现。