Qt图形框架
环境准备
-
安装Ubuntu虚拟机并配置远程
- 安装完系统后安装Xrdp
sudo apt-get update sudo apt-get xrdp sudo systemctl status xrdp
- 安装完系统后安装Xrdp
-
设置root可以远程桌面登录
# 允许root用户远程ssh登录 sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config # 允许使用密码连接ssh服务 sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config # 重启ssh服务 sudo service sshd restart sudo su - root passwd root #设置root密码 确认密码 restart
-
测试连接
一、 Qt的概述
Qt(跨平台的C++ GUI应用程序开发框架)
常见:
1)控件类:QT += widgets
类名 | 功能 |
---|---|
QApplication | Qt的gui应用程序 |
QWidget | 控件基类 |
QLabel | 标签 |
QPushButton | 按钮 |
QDialog | 对话框 |
QMainWindow | 主窗口 |
QSlider | 滑块 |
QSpinBox | 选值框 |
QLineEdit | 行编辑 |
QFrame | 显示框架 |
QMessageBox | 消息提示框 |
QListWidget | 列表窗口 |
QTableView | 表格视图 |
QLayout | 布局器 |
QSpacerItem | 间隔器 |
2)Qt核心类:QT += core gui
类名 | 功能 |
---|---|
QObject | 最顶层的基类 |
QString | 字符串 |
QTextCodec | 字符编码 |
QPainter | 画家类 |
QImage | 图片 |
QRect | 矩形区域 |
QPoint | 位置 |
QSize | 大小 |
QDir | 目录 |
QTime | 时间 |
QTimer | 定时器 |
QPaintEvent | 绘图事件 |
QTimerEvent | 定时器事件 |
QMouseEvent | 鼠标事件 |
QKeyEvent | 键盘事件 |
3)Qt数据库 QT += sql
类名 | 功能 |
---|---|
QSqlDatabase | 建立Qt和数据库连接 |
QSqlQuery | 执行SQL语句 |
QSqlQueryModel | 保存查询结果集 |
4)Qt网络编程 QT += network
类名 | 功能 |
---|---|
QAbstractSocket | 套接字基类 |
QTcpServer | TCP服务器 |
QTcpSocket | TCP套接字 |
QUdpSocket | UDP套接字 |
QHostAddress | IP地址 |
1. Qt发展历史
- 1991年诞生,Haavard Nord和Eirik Chambe-Eng合作编写最初的Qt
- 1994年Haavard Nord和Eirik Chambe-Eng创立奇趣科技(Trolltech)公司
- 2005年Qt4.0发布
- 2008年奇趣科技公司被诺基亚收购
- 2009年Qt源代码开放
- 2012年诺基亚将Qt业务和全部知识产权出售给Digia公司
- 2013年Qt5.0发布
- 2014年Digia成立子公司The Qt Company
2. Qt5.4安装和配置
-
官网安装教程:https://resources.qt.io/learning-hub/introduction-to-qt-installing-qt-creator
-
注:根据提示,默认安装在主目录下,选择一个版本安装就可以
-
配置环境变量
1)sudo vim /etc/profile
最后插入这二行
export PATH= P A T H : / h o m e / q t / Q t / 6.2.3 / g c c 6 4 / b i n e x p o r t P A T H = PATH:/home/qt/Qt/6.2.3/gcc_64/bin export PATH= PATH:/home/qt/Qt/6.2.3/gcc64/binexportPATH=PATH:/home/qt/Qt/Tools/QtCreator/bin2)修改用户加载
vim ~/.bashrc // 有些系统是 .bash 文件名
最后一行添加 source /etc/profile -
重启系统测试
执行“qmake -v”正常看到Qt的版本信息
执行“qtcreator”正常可以进入Qt的集成开发环境界面问题:提示缺少libgstreamer…相关库
解决:在线安装sudo apt-get install libgstreamer0.10-0 sudo apt-get install libgstreamer-plugins-base0.10-0
问题:编译Qt程序时提示缺少libgl…相关库(没有安装openGL)
解决:在线安装sudo apt-get install libgl1-mesa-devs
3. Qt相关的工具介绍
- Qt助手(assistant) //Qt帮助手册
- Qt构建器(qmake) //构建Qt应用程序
- Qt设计师(designer) //图形界面编辑器
- Qt界面编译器(uic) //将设计师得到xml(.ui)文件转换为C++文件(.h)
- Qt元对象编译器(moc) //将Qt中语法扩展还原为标准C++代码
- Qt资源编译器(rcc) //将图片资源转换为C++文件(.cpp)
- Qt创造器(qtcreator) //Qt的集成开发环境(IDE),包含上面所有工具
4. Qt助手的使用
eg:QApplication/QLabel
- 先看第一句话,了解该类的功能,如果看不懂,可以点击"more"查看详细说明。
- 接着往下看,了解头文件(和类名一致),构建选项(QT+=widgets),继承关系。
- 类中成员变量(Properties)
- 公有的成员函数(Public Functions)
- 公有的虚函数(Reimplemented Public Functions)
- 槽函数(Public Slots)//Qt语法扩展
- 信号函数(Signals)//Qt语法扩展
- 静态公有成员(Static Public Members)
- 保护虚函数(Reimplemented Protected Functions)
- 宏(Macros)
- 详细说明(Detailed Description)
练习:看QLabel(标签)帮助手册
二、 第一个Qt程序
-
创建工程目录
mkdir Hello
注:每个Qt应用程序都应该放在独立的工程目录下 -
进入工程目录,编写源代码(c++)
cd Hello
vi main.cpp
#include <QApplication>
#include <QLabel> //标签控件
int main(int argc,char** argv){
//构建QT应用程序o
QApplication app(argc,argv);
//创建标签控件(图形对象,部件,构件,组件);
QLabel label("Hello Qt");
//显示标签控件
label.show();
return 0;
}
-
执行“qmake -project”,得到工程文件(Hello.pro)
注意:一般需要添加“QT += widgets”,表示需要用和widgets模块对应的头文件和库文件 -
执行“qmake”,根据工程文件得到Makefile
-
执行“make”完成编译和链接
如果没有问题会得到可执行程序"Hello";如果有语法错误,修改源代码再次执行“make”即可,前面3、4步不必重复执行。 -
测试运行,可以看到标签窗口
./Hello
练习:创建一个Qt应用程序,里面包含一个QPushButton(按钮),显示文本Button.
参考代码:
#include <QApplication>
#include <QPushButton>
int main(int argc,char* argv[]){
QApplication app(argc,argv);
//创建按钮控件
QPushButton button("Button");
//显示按钮控件
button.show();
return app.exec();
}
注意:
如果报错找不到 /usr/bin/ld: 找不到 -lGL
执行命令安装包:
sudo apt-get install libgl1-mesa-dev
```
<br>
<br>
## 三、 Qt字符串(QString)和字符编码
1. **常见编码**
1)windows默认使用ANSI(中文gbk编码,英文ACKII)
2)linux默认使用unicode(utf-8)
3)Qt字符串QString内部默认使用unicode(utf-16)
2. **编码转换(QTextCodec)**
//创建GBK编码转换对象
QTextCodec *codec = QTextCodec::codecForName("GBK");
//使用编码对象,将参数中文字符串转换为unicode编码字符串
QString string = codec->toUnicode("GBK编码中文字符串");
注意:
使用vi的底行命令可以查看或设置源代码编码方式
set fileencoding //查看现在设置编码
set fileencoding=gbk //设置GBK编码(euc-cn,cp936)
```c
#include <QApplication>
#include <QPushButton>
#include <QTextCodec>
int main(int argc,char* argv[]){
QApplication app(argc,argv);
//1)创建编码转换对象
QTextCodec* codec = QTextCodec::codecForName("GBK");
//(2)将要显示的字符串转换为QT内部的unicode编码
QString str = codec->toUnicode("下午听课有点困");
//创建按钮控件
QPushButton button(str);
//显示按钮控件
button.show();
return app.exec();
}
练习:
创建Qt应用程序对象,里面包含一个标签(QLabel)和一个按钮(QPushButton),标签显示文本“我是标签”,按钮显示文本“我是按钮”:
1)正常构建,6步,结果ok
2)使用vi底行命令,设置编码gbk,再次执行make,结果中文乱码
3)使用QTextCodec实现编码转换,再次执行make,结果又可以正确显示
参考代码:main.cpp 工程目录需要添加 QT+=widgets QT+=core5compat
#include <QApplication>
#include <QLabel>
#include <QTextCodec>
#include <QPushButton>
int main(int argc,char* argv[]){
QApplication app(argc,argv);
QLabel label("我是标签");
label.show();
QPushButton button("我是按钮");
button.show();
return app.exec();
}
三、父窗口(容器窗口)
-
常用的父窗口类
–》QWidget //控件基类
–》QDialog //对话框,QWidget的子类
–》QMainWindow //主窗口,QWidget的子类 -
QWidget中两个常用的函数
–》调整控件或父窗口位置
void move(int x,int y);
–》调整控件或父窗口大小
void resize(int w,int h);
注意:
在Qt中new对象如果指定了父窗口,那么可以不用delete,因为在父窗口对象销毁时会自动将其销毁掉。
参考代码:main.cpp
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QMainWindow> //主窗口
#include <QDialog> //对话框
#include <QWidget> //控件基类
int main(int argc,char** argv){
QApplication app(argc,argv);
//创建父窗口
//QMainWindow parent;
QDialog parent; //居中大小均匀
//QWidget parent; //靠左上角显示
//创j标签和按钮控件并停靠在父窗口上面
QLabel label("我是标签",&parent);
QPushButton button("确认修改",&parent);
//设置父窗口和每个控件大小和位置
parent.resize(480,320);
label.move(30,50);
button.move(220,280);
//显示父窗口,上面停靠的控件也会一起被显示
parent.show();
return app.exec();
}
四、信号和槽机制(Signal&slot)
1. 概念
信号和槽是Qt中自行定义的一种通信机制,实现对象之间的交互,当某个对象发生改变时将会发送信号,该信号可以被其它对象接收,接收以后将执行一个指定的成员函数(槽函数).
2. 定义
- 包含信号或槽的类必须是QObject的子类
- 信号使用“signals:”标记,信号函数只需声明,不能写定义
- 槽使用“public slots:”标记,槽函数可以和某个信号建立连接,通过某个信号触发槽函数的执行;另外槽函数也可以当做是普通的成员函数,直接调用
- 包含信号或槽的类,前面需要添加宏"Q_OBJECT",将来构建工程时,会调用moc(元对象编译器)将语法扩展的信号或槽还原为标准C++代码.
class XX:public QObject{
Q_OBJECT //moc
signals:
void sigFunc(void);//信号函数
public slots:
void slotFunc(void){
...}//槽函数
};
3. 信号和槽连接
QObject::connect(
const QObject* sender, //信号发送对象,可以是QObject所有子类类型
const char* signal, //要发送的信号函数
const QObject* receiver, //信号接收对象,可以是QObject所有子类类型
const char* method ); //接收信号后要执行的槽函数
注意:
SIGNAL(信号函数(参数表)) //将信号函数转换为const char*
SLOT(槽函数(参数表)) //将槽函数转换为const char*
案例:
创建一个Qt应用程序,里面包含一个标签和两个控件,实现点击按钮关闭标签。
按钮点击时发送信号:clicked()
实现标签关闭功能的槽:close()
增加一个退出按钮
参考代码:close.cpp
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QDialog>
int main(int argc,char **argv){
QApplication app(argc,argv);
QDialog parent; //父窗口
QLabel label("我是一个标签",&parent); //栈对象
QPushButton *button = new QPushButton("我是一个标签",&parent); //堆对象
QPushButton *button2 = new QPushButton("退出",&parent); //堆对象关闭按钮
parent.resize(480,320);//父窗口大小
label.move(50,50); //标签位置
button->move(50,200);//按钮位置
button2->move(240,200);//按钮位置
parent.show(); //显示父窗口
//实现点击按钮关闭标签功能
QObject::connect(button,SIGNAL(clicked(void)),&label,SLOT(close(void)));
QObject::connect(button2,SIGNAL(clicked(void)),&app,SLOT(closeAllWindows())/*SLOT(quit())*/);
return app.exec();
}
4. 信号和槽连接的语法要求
-
信号和槽参数要一致
QObject::connect(A,SIGNAL(sigFunc(int)),B,SLOT(slotFunc(int))); //ok
QObject::connect(A,SIGNAL(sigFunc(void)),B,SLOT(slotFunc(int))); //error -
可以带有缺省参数
class B{
Q_OBJECT
public slots:
void slotFunc(int i=0){}
};
QObject::connect(A,SIGNAL(sigFunc(void)),B,SLOT(slotFunc(void)));//ok -
信号函数的参数可以比槽函数参数多,多余参数将被忽略
QObject::connect(A,SIGNAL(sigFunc(int)),B,SLOT(slotFunc(void)));//ok -
一个信号可以同时连接多个槽函数(一对多)
QObject::connect(A,SIGNAL(sigFunc(int)),B1,SLOT(slotFunc1(int)));//ok
QObject::connect(A,SIGNAL(sigFunc(int)),B2,SLOT(slotFunc2(int)));//ok
注意:
如果A对象发送喜好,B1和B2的槽函数都会被执行 -
多个信号可以同时连接到同一个槽函数(多对一)
QObject::connect(A1,SIGNAL(sigFunc1(int)),B,SLOT(slotFunc(int)));//ok
QObject::connect(A2,SIGNAL(sigFunc2(int)),B,SLOT(slotFunc(int)));//ok
注意:
无论A1或A2发送信号,B的槽函数都会被执行 -
两个信号函数可以直接连接(信号串联) //了解
QObject::connect(A1,SIGNAL(sigFunc1(int)),A2,SIGNAL(sigFunc2(int)));//ok
注意:
当A1发送信号时,所连接的A2对象的信号也将被发送.
案例:
创建Qt应用程序,包含一个滑块(QSlider)和选值框(QSpinBox),通过信号和槽的机制,并让它们保持同步运行。
QSlider //滑块
void setValue(int)[slot]; //设置当前位置
void valueChanged(int value)[signal]; //滑块滑动时发送信号
QSpinBox //选值框
void setValue(int)[slot]; //设置当前数值
void valueChanged(int value)[signal]; //选值框数值改变时发送信号
参考代码:main.cpp
#include <QApplication>
#include <QSlider> //滑块
#include <QSpinBox> //选值框
#include <QDialog>
int main(int argc,char **argv){
QApplication app(argc,argv);
QDialog parent; //父窗口
parent.resize(200,100);
//创建水平滑块控件并停靠在父窗口上面
QSlider slider(Qt::Horizontal,&parent);
slider.move(20,30);
slider.setRange(0,50); //设置数据变化范围
//创建选值框控件并停靠在父窗口上面
QSpinBox spin(&parent);
spin.move(120,30);
spin.setRange(0,50); //设置数据变化范围
//显示父窗口
parent.show();
//滑动滑块,选值框随之改变
QObject::connect(&slider,SIGNAL(valueChanged(int)),&spin,SLOT(setValue(int)));
//选值框数据改变,滑块随之滑动
QObject::connect(&spin,SIGNAL(valueChanged(int)),&slider,SLOT(setValue(int)));
return app.exec();
}
五、面向对象的QT编程
完全不使用任何面向对象技术,而只是利用Qt所提供的类创建对象,并调用对象的接口一满足用户的需求是可能的,但这样构建的QT应用程序其功能必然是
十分有限的:
- 首先,Qt类保护成员中的诸多实现无法在类的外部被复用,Qt试图通过多态实现的很多机制,如事件处理,完全无法使用
- 再次,Qt提供的信号和槽不可能满足用户所有的需求,自定义信号和槽需要面向对象技术
- 最后,Qt设计师,QT创造器等工具链都在以面向对象的方式使用Qt,反其道而行之不会有好结果
案例1:
所谓面向对象的Qt编程就是将C++的面向对象语法特性和Qt图形框架相结合,这里通过面向对象的编程思想实现一个加法计算器案例
- 输入两个数字,按‘=’按钮显示就算结果
- 两个操作数必须都是合法的数字,拒绝接受任何非法字符
- 两个操作数必须全部合法,‘=’按钮才被激活,否则禁用(不可以点击)
- 显示结果的控件只可查看不可修改,但支持复制到剪贴板
- 所有子窗口的大小和位置随主窗口的缩放自动调整至最佳
参考代码:CalculatorDialog.h CalculatorDialog.cpp main.cpp
touch {CalculatorDialog.h,CalculatorDialog.cpp,main.cpp}
代码1:CalculatorDialog.h
#ifndef __CALCULATORDIALOG_H
#define __CALCULATORDIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QTextCodec>
#include <QLineEdit> //行编辑控件
#include <QDoubleValidator> //数字验证器
#include <QHBoxLayout> //水平布局器
#include <QFont> //字体
//继承QDialog,当前类就也是父窗口类
class CalculatorDialog:public QDialog{
Q_OBJECT //moc
public:
//构造函数
CalculatorDialog(void);
public slots: //自定义槽函数
//设置按钮为正常或禁用状态的槽函数
void enableButton(void);
//点击按钮计算结果的槽函数
void calcClicked(void);
private:
QLineEdit* m_editX; //左操作数
QLineEdit* m_editY; //右操作数
QLineEdit* m_editZ; //显示计算结果
QLabel* m_label; //加号 “+”
QPushButton* m_button; //等号“=”
QHBoxLayout* m_hBoxLayout; //水平布局器
};
#endif //__CALCULATORDIALOG_H
代码2:CalculatorDialog.cpp
#include "CalculatorDialog.h"
//构造函数
CalculatorDialog::CalculatorDialog(void){
setWindowTitle("计算器"); //窗口标题
QFont font; //字体
font.setPointSize(20); //字体大小:20
setFont(font); //设置字体
//左操作数,参数this表示父窗口指针
m_editX = new QLineEdit(this);
//设置文本对齐方式:右对齐
m_editX->setAlignment(Qt::AlignRight);
//设置数字验证器,只能输入数字形式的文本内容
m_editX->setValidator(new QDoubleValidator(this));
//右操作数
m_editY = new QLineEdit(this);
m_editY->setAlignment(Qt::AlignRight);
m_editY->setValidator(new QDoubleValidator(this));
//显示计算结果
m_editZ = new QLineEdit(this);
m_editZ->setAlignment(Qt::AlignRight);
m_editZ->setReadOnly(new QDoubleValidator(this));
//"+"
m_label = new QLabel("+",this);
//"="
m_button = new QPushButton("=",this);
m_button->setEnabled(false); //设置按钮禁用状态
//布局器:自动调整大小和位置
m_hBoxLayout = new QHBoxLayout(this);
//将控件按水平方向添加到布局器中
m_hBoxLayout->addWidget(m_editX);
m_hBoxLayout->addWidget(m_label);
m_hBoxLayout->addWidget(m_editY);
m_hBoxLayout->addWidget(m_button);
m_hBoxLayout->addWidget(m_editZ);
//设置布局器
setLayout(m_hBoxLayout);
//连接信号和槽函数
//左右操作数文本改变时,将会发送textChaned信号,连接设置按钮为正常或禁用状态的槽函数
connect(m_editX,SIGNAL(textChanged(QString)),this,SLOT(enableButton(void)));
connect(m_editY,SIGNAL(textChanged(QString)),this,SLOT(enableButton(void)));
//点击等号按钮,发送clicked信号,连接计算结果的槽函数
connect(m_button,SIGNAL(clicked(void)),this,SLOT(calcClicked(void)));
}
//设置按钮为正常或禁用状态的槽函数
void CalculatorDialog::enableButton(void){
bool bXOk,bYOk;
//text():获取文本内容(QString)
//toDouble();将QString转换为字符串,如果转换失败将bXOk置false,成功置true
m_editX->text().toDouble(&bXOk);
m_editX->text().toDouble(&bYOk);
//如果左右操作数都输入有效数据,设置按钮为正常状态否则设置禁用状态
m_button->setEnabled(bXOk && bYOk);
}
//点击按钮计算结果的槽函数
void CalculatorDialog::calcClicked(void){
//计算相加结果
double res = m_editX->text().toDouble()+m_editY->text().toDouble();
//将结果转为QString,number:将参数的数字转换为QString
QString str = QString::number(res);
//显示结果结果
m_editZ->setText(str);
}
代码3:main.cpp
#include <QApplication>
#include "CalculatorDialog.h"
int main(int argc,char **argv){
QApplication app(argc,argv);
CalculatorDialog dialog;
dialog.show();
return app.exec();
}
编译:
#1. 执行
qmake -project
#2. 在Calculator.pro 工程文件里面追加
QT+=widgets
QT+=core5compat
#3.执行
qmake
#4.执行
make
测试
./Calculator
案例2
- 获取系统时间
–》使用面向对象的Qt编程方法创建获取时间的窗口
–》点击获取时间按钮,通过自定义的槽函数获取时间并显示到标签
提示:
```
class TimeDialog:public QDialog{
Q_OBJECT
public:
TimeDialog(void){界面初始化,信号和槽连接}
public:
void getTime(void){//获取系统时间的槽函数
Qtime time = QTime::currentTime();
time.toString("hh:mm:ss");
//将字符串时间显示到Label
}
private:
QLabel *m_label;
QPushButton* m_button;
};
```
参考代码:TimeDialog.h , TimeDialog.h ,main.cpp
touch {TimeDialog.h , TimeDialog.h ,main.cpp}
代码1:TimeDialog.h
#ifndef __TIMEDIALOG_H
#define __TIMEDIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout> //垂直布局器
#include <QFont>
#include <QTime> //时间
class TimeDialog:public QDialog{
Q_OBJECT
public:
TimeDialog(void); //构造汉函数
public slots:
void getTime(void); //获取系统时间的槽函数
private:
QLabel* m_label; //显示时间标签
QPushButton* m_button; //获取时间的按钮
QVBoxLayout* m_vBoxLayout; //垂直布局器
};
#endif //__TIMEDIALOG_H
代码2:TimeDialog.cpp
#include "TimeDialog.h"
//构造函数
TimeDialog::TimeDialog(void){
//界面初始化
setWindowTitle("系统时间"); //设置窗口标题
QFont font;
font.setPointSize(20);
setFont(font); //设置字体大小
m_label = new QLabel(this); //显示系统时间标签
//设置标签边框样式:凹陷面板
m_label->setFrameStyle(QFrame::Panel|QFrame::Sunken);
//设置文本方式:水平和垂直都居中
m_label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
m_button = new QPushButton("获取系统时间",this);
//设置垂直布局器:自动调正大小和位置
m_vBoxLayout = new QVBoxLayout(this);
m_vBoxLayout-> addWidget(m_label);
m_vBoxLayout->addWidget(m_button);
setLayout(m_vBoxLayout);
//信号和槽连接,点击获取时间按钮,发送clicked信号连接到获取时间的槽函数
connect(m_button,SIGNAL(clicked(void)),this,SLOT(getTime(void)));
}
//获取系统时间的槽函数
void TimeDialog::getTime(void){
QTime time = QTime::currentTime(); //获取系统时间
QString str = time.toString("hh:mm:ss"); //将时间转换为QString
m_label->setText(str); //将字符串时间显示到label控件上
}
代码3:main.cpp
#include <QApplication>
#include "TimeDialog.h"
int main(int argc,char** argv){
QApplication app(argc,argv);
TimeDialog dialog;
dialog.show();
return app.exec();
}
添加:QT+=widgets
编译
qmake -project
qmake
make
六、Qt设计师使用(designer)
什么是QT设计师?
Qt设计师(designer)是Qt工具,用于设计和构建带有Qt控件的图形用户界面GUI应用程序,它使用"所见即所得"的方式编写自定义窗口或对话框,可以方便的修改窗口
及控件的大小,位置,字体等相关属性,同时可以方便的预览界面效果
Qt设计师中用可以通过鼠标直接拖曳这些窗口控件,设置相关属性,能够高效、快速实现图形用户的设计,让界面实现更加直观形象,并可以自动生成和界面相关代码,
进而简化编程,提高代码编写效率
案例:使用设计师重构加法计算器
1. 创建工程目录
mkdir Calculator2
2. 进入工程目录,执行“designer”启动设计师
1)在新建窗体界面,选择模板(父窗口):“Dialog without Buttons”
2)在设计师界面中完成ui设计
–》从“Widget Box”里面找到需要使用控件,拖拽到父窗口上面
PushButton(1个) LineEdit(3个) Label(1个)
–》设置父窗口和每个控件的属性
父窗口(QDialog):
objectName(对象名):CalculatorDialog
注:将来会根据父窗口的对象名生成一个名字相同类,包含在设计师完成的所有代码
font(字体):点大小(20)
windowTitle(标题):加法计算器
左操作数(QLineEdit)
objectName:m_editX
alignment:水平(AlignRight)
右操作数(QLineEdit)
objectName:m_editY
alignment:水平(AlignRight)
显示结果(QLineEdit)
objectName:m_editZ
alignment:水平(AlignRight)
readOnly(只读):勾选√
加号标签:
objectName:m_label
text:“+”
等号按钮:
objectName:m_button
enabled:去掉勾选√(禁用)
text:“=”
–》调整父窗口和控件的大小和位置
方法1:鼠标拖拽
方法2:键盘,调整位置(方向键、ctrl+方向键) 调整大小(shitf+方向键、ctrl+shift+方向键)
方法3:设置geometry属性,调整位置(x,y) 大小(宽度,高度)
方法4:使用布局器自动调整 //推荐
使用布局器自动调整
–》窗体预览
–》保存(ctrl+s),指定文件名“CalculatorDialog.ui”
–》关闭,最终在工程目录下得到一个"CalculatorDialog.ui"文件
如果需要重新编辑:
designer CalculatorDialog.ui
3. 使用界面编辑器(uic),
将“CalculatorDialog.ui(xml)”转换为“ui_CalculatorDialog.h(c++)”
-
转换命令
uic CalculatorDialog.ui -o ui_CalculatorDialog.h -
转换后“ui_CalculatorDialog.h”文件内容
class Ui_CalculatorDialog{ public: 图形控件相关对象指针声明; void setupUi(QDialog*){ //界面初始化 创建图形控件、属性设置.. } }; namespace Ui{ class CalculatorDialog:public Ui_CalculatorDialog{ }; }
注:Ui名字空间的子类(Ui::CalculatorDialog)和上面基类(Ui_CalculatorDialog)相同
4. 使用“ui_CalculatorDialog.h”文件,复用里面代码方法
-
方法1:继承
class MyClass:public Ui::CalculatorDialog{
//将界面相关代码继承过来直接使用
}; -
方法2:组合
```c
class MyClass{
public:
MyClass():ui(new Ui::CalculatorDialog){}
private:
//通过“ui->”访问和界面相关代码
Ui:: CalculatorDialog* ui;
};
```
5. 编写代码、构建、测试
1)继承方式
参考代码1:CalculatorDialog.h 继承了父窗口
#ifndef __CALCULATORDIALOG_H
#define __CALCULATORDIALOG_H
#include "ui_CalculatorDialog.h"//继承方式
//自定义计算器窗口类,继承了父窗口,那么当前类就也是一个父窗口
class CalculatorDialog:public QDialog,public Ui::CalculatorDialog{
Q_OBJECT
public:
//构造函数
CalculatorDialog(void);
public slots:
//恢复按钮为正常状态槽函数
void enableButton(void);
//计算和显示结果的槽函数
void calcClicked(void);
};
#endif//__CALCULATORDIALOG_H
参考代码2:CalculatorDialog.cpp 使用setupUi(this); 界面初始化
#include "CalculatorDialog.h"
//构造函数
CalculatorDialog::CalculatorDialog(void){
//界面初始化
setupUi(this);
m_editX->setValidator(new QDoubleValidator(this));//设置验证器
m_editY->setValidator(new QDoubleValidator(this));//设置验证器
//信号和槽连接
//左右操作数文本改变时,发送信号textChanged(QString)
//注:如果连接的槽函数是当前父窗口中自定义的,那么第三个参数一定
//是this.
connect(m_editX,SIGNAL(textChanged(QString)),
this,SLOT(enableButton(void)));
connect(m_editY,SIGNAL(textChanged(QString)),
this,SLOT(enableButton(void)));
//点击等号按钮,发送信号clicked()
connect(m_button,SIGNAL(clicked(void)),
this,SLOT(calcClicked(void)));
}
//恢复按钮为正常状态槽函数
void CalculatorDialog::enableButton(void){
bool bXOk;//记录左操作数是否输入了有效数据
bool bYOk;//记录右操作数是否输入了有效数据
//text():获取文本内容(QString)
//toDouble():将QString转换为double,参数保存转换是否成功结果
m_editX->text().toDouble(&bXOk);
m_editY->text().toDouble(&bYOk);
//如果左右操作数都输入了有效数据,则恢复按钮为正常可用状态,否则
//设置为禁用状态.
m_button->setEnabled(bXOk && bYOk);
}
//计算和显示结果的槽函数
void CalculatorDialog::calcClicked(void){
//计算相加结果
double res = m_editX->text().toDouble() +
m_editY->text().toDouble();
//将数字结果转换为字符串
//number():将double转换为QString
QString str = QString::number(res);
//显示结果
//setText():设置控件要显示的文本
m_editZ->setText(str);
}
参考代码3:main.cpp
#include <QApplication>
#include "CalculatorDialog.h"
int main(int argc,char** argv){
QApplication app(argc,argv);
CalculatorDialog dialog;
dialog.show();
return app.exec();
}
构建、测试
qmake -project
#添加QT+=widgets
qmake
make
2)组合方式
参考代码1:CalculatorDialog.h 继承了父窗口
#ifndef __CALCULATORDIALOG_H
#define __CALCULATORDIALOG_H
#include "ui_CalculatorDialog.h"//组合方式
//自定义计算器窗口类,继承了父窗口,那么当前类就也是一个父窗口
class CalculatorDialog:public QDialog{
Q_OBJECT
public:
//构造函数
CalculatorDialog(void);
//析构函数
~CalculatorDialog(void)