1. QT概述
- 跨平台的C++图形用户界面应用程序框架
- 成功案例(只列三个)
- linux桌面系统KDE
- WPS 办公软件
- 谷歌地图
2. QT文件解释
QT += core gui //QT 包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //4版本后,加入 widgets模块
CONFIG += c++11 //C++11版本
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \ //源文件
main.cpp \
mywidget.cpp
HEADERS += \ //头文件
mywidget.h
qnx: target.path = /tmp/$${TARGET}/bin //目标 生成exe
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
#include "mywidget.h" //包含mywidget头文件
#include <QApplication> //应用程序类
//main 程序入口
//argc 命令行变量数量 argv 命令行变量数据
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //应用程序对象 , QT中有且只有一个
MyWidget w; //创建一个自定义窗口
w.show(); //窗口对象默认不会弹出,需要调用show函数
return a.exec(); //进入消息循环机制,相当于阻塞,点×就退出循环
}
#ifndef MYWIDGET_H
#define MYWIDGET_H //防止头文件重复包含
#include <QWidget> //QWidget是当前的基类
class MyWidget : public QWidget //继承基类
{
Q_OBJECT //Q_OBJECT 提供了Qt中的信号和槽的机制
public:
MyWidget(QWidget *parent = nullptr); //默认构造
~MyWidget(); //析构函数
};
#endif // MYWIDGET_H
#include "mywidget.h"
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent) //初始化列表 用户如果没有传参,就用默认参数的在头文件中
{
}
MyWidget::~MyWidget()
{
}
3.命名规范和常用快捷键
- 类名 ——首字母大写,单词和单词之间 ——首字母大写(大驼峰)
- 函数名、变量名称 ——首字母小写,单词和单词间——首字母大写(小驼峰)
常用快捷键
- 运行——ctrl+R
- 编译——ctrl+B
- 帮助文档——F1
- 注释——ctrl+/
- 字体缩放——ctrl+滚轮
- 整行代码移动——ctrl+shift+↑或者↓
- 查找——ctrl+F
- 自动对齐——ctrl+i
- 同名之间的.h和.cpp切换——ctrl+F4
4. QPushButton简单使用
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent) //初始化列表 用户如果没有传参,就用默认参数的在头文件中
{
QPushButton *btn = new QPushButton;
//btn->show(); //show方法,默认以顶层方式弹出窗口
//预期让按钮 依赖于 MyWidget窗口中
btn->setParent(this); //this本类指针
//显示文本
btn->setText("孙悟空");
//创建第二个按钮
QPushButton *btn1 = new QPushButton("猪八戒");
btn1->setParent(this);
//移动按钮
btn1->move(100,100);
//设置窗口大小
this->resize(600,400);
//设置窗口标题
this->setWindowTitle("第一个项目");
//设置固定窗口大小
this->setFixedSize(600,400);
}
5. Qt中的对象树
- Qt简化了对象释放
- 在创建对象时,如果父类是QObject或者QObject派生的类,这个对象可以不用去管理释放,会放到一个对象树上,析构会自动管理对象和释放
- 构造的顺序和析构的顺序是相反的
6.Qt中的坐标系
- 左上角是原点,水平向右是X的正方向,垂直向下是Y的正方向
7. Qt中的信号和槽
- 优点:松散耦合,将不相关的两个内容链接到一起
7.1 点击按钮关闭窗口
#include "widget.h"
#include<QPushButton>
#include"mypushbutton.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建自定义按钮
MyPushButton *mybtn = new MyPushButton;
mybtn->setParent(this);
mybtn->setText("自定义按钮");
mybtn->move(250,150);
//点击 按钮关闭窗口
//利用connect进行链接
//参数1——信号发送者(指针) 参数2——发送的信号(信号的地址)
//参数3——信号接收者(指针) 参数4——处理槽函数(槽函数地址)
QObject::connect(mybtn,&MyPushButton::clicked,this,&Widget::close);
// QObject::connect(mybtn,&QPushButton::clicked,this,&QWidget::close);
}
7.2 自定义信号和槽
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
//自定义信号 写到 signals下
signals:
//自定义信号写法
//1.无返回类型 void
//2.信号只需要声明,不需要实现
//3.自定义信号可以发生重载
void hungry();
};
#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
//自定义槽函数 写到public slots下,或者 全局函数 或者是 public下, 或者是lambda表达式
public slots:
//1、返回值void
//2、需要声明,也需要实现
//3、也可以发生重载
void treat();
};
#endif // STUDENT_H
#include "student.h"
#include<QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
qDebug() << "请客吃饭" << endl;
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"student.h"
#include"teacher.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//下课函数
void classIsOver();
Teacher *t;
Student *s;
};
#endif // WIDGET_H
#include "widget.h"
/*
需求:
teacher类 student类
下课的时候,老师发送自定义信号,饿了
学生 响应饿了的信号,并且 请老师吃饭
*/
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建老师和学生对象
this->t = new Teacher(this);
this->s = new Student(this);
//链接信号和槽
QObject::connect(this->t,&Teacher::hungry,this->s,&Student::treat);
this->classIsOver();
}
Widget::~Widget()
{
}
void Widget::classIsOver()
{
//自定义信号触发 emit
emit this->t->hungry();
//t写成成员指针变量,widget类内就能访问到
//如果在widget构造函数里局部定义t,这里就访问不到
//但如果在构造函数里就调用 emit 则可以访问到
}
7.3 自定义和槽扩展
- 当发生重载的时候,需要用函数指针来指明函数地址
- 信号可以链接信号
- 一个信号可以链接多个槽函数
- 多个信号可以链接同一个槽函数
- 信号和槽函数的参数类型 必须一一对应,参数个数可以不一致,信号的个数可以多于槽函数,但是不多于的部分,参数类型得一一对应
- 点击按钮事件,只能触发无参的信号,不能触发有参的信号
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
void hungry();
void hungry(QString foodname);
};
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:
void treat();
void treat(QString foodname);
};
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
qDebug() << "请客吃饭" << endl;
}
void Student::treat(QString foodname)
{
//让宫保鸡丁的双引号消失
//将QString转为char *
//先调用 .toUtf8()转为QbyteArray类型
//在调用.data()转为char *
qDebug() << "请客吃饭,老师要吃:"<< foodname.toUtf8().data() << endl;
}
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
this->t = new Teacher(this);
this->s = new Student(this);
//链接信号和槽
//指针->地址
//函数指针->函数地址
//void(Teacher::* teacherSignals)(QString) = &Teacher::hungry;
//void(Student::* studentSlots)(QString) = &Student::treat;
//QObject::connect(this->t,teacherSignals,this->s,studentSlots);
//信号和槽 可以断开链接
//QObject::disconnect(this->t,teacherSignals,this->s,studentSlots);
//信号可以链接信号
//this->classIsOver();
QPushButton *btn = new QPushButton(this);
this->resize(600,400);
btn->setText("下课");
void(Teacher::* teacherSignals1)() = &Teacher::hungry;
void(Student::* studentSlots1)() = &Student::treat;
QObject::connect(this->t,teacherSignals1,this->s,studentSlots1);
//用click触发老师饿了信号
QObject::connect(btn,&QPushButton::clicked,this->t,teacherSignals1);
//2.一个信号可以链接多个槽
QObject::connect(btn,&QPushButton::clicked,this,&QWidget::close);
}
Widget::~Widget()
{
}
void Widget::classIsOver()
{
//自定义信号触发 emit
emit this->t->hungry("宫保鸡丁");
}
7.4 QT4版本的信号和槽
connect(t,SIGNAL(hungry(QString)),s,SLOT(treat(QString)));
//不建议使用,参数类型不做检测,
this->classIsOver();
7.5 Lambda表达式
- c++11中的Lambda表达式用于定义并创建匿名的函数对象
[capture](parameters)mutable->return-type{ statement}
- [ ]标识一个lambda表达式的开始,不能省略
//[=] 所在作用范围内所有可见的局部变量
//并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)
//[&]按引用传递, btn进入只读状态,不能进行修改
//推荐使用[=]
//[this] 函数体内可以使用lambda所在类中的成员变量
connect(btn,&QPushButton::clicked,this,[=](){
btn->setText("aaa");
})
mutalble
,声明后,可以修改按值传递进来的拷贝
QPushButton *myBtn = new QPushButton(this);
QPushButton *myBtn1 = new QPushButton(this);
myBtn->move(200,100);
myBtn1->move(300,100);
int m = 10;
connect(myBtn,&QPushButton::clicked,this,[m]()mutable{
m = 20; qDebug() << m;});
connect(myBtn1,&QPushButton::clicked,this,[=]()mutable{
qDebug() << m;});
qDebug() << m;
})
- -> 返回值+类型
int n = 10;
n = []()->int{return 10000}(); //最后的小括号,是函数调用
8. QMainWindow
- 为用户提供主窗口程序的类,包含一个菜单栏(menu bar),多个工具栏(tool bars),多个锚接部件(dock widgets),一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等。
- 只能有一个的,用系统方法创建,并且用set方法添加到窗口
- 可以有多个的,用自己的方法创建,用add方法添加到窗口
#include "mainwindow.h"
#include<QMenuBar>
#include<QToolBar>
#include<QPushButton>
#include<QStatusBar>
#include<QLabel>
#include<QDockWidget>
#include<QTextEdit>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->resize(600,400);
/************************* 菜单栏 只能有一个 *************************/
QMenuBar * bar = menuBar();
//将菜单栏设置到窗口中
setMenuBar(bar);
//添加菜单
QMenu *fileMenu = bar->addMenu("文件");
QMenu *editMenu = bar->addMenu("编辑");
//添加菜单项
QAction * newAction = fileMenu->addAction("新建");
//添加分割线
fileMenu->addSeparator();
QAction * openAction = fileMenu->addAction("打开");
/************************* 菜单栏 只能有一个 *************************/
/************************* 工具栏 可以有多个 *************************/
QToolBar * toolBar = new QToolBar(this);
//将工具栏放入窗口
addToolBar(Qt::LeftToolBarArea,toolBar);
//只允许上下停靠
toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
//取消浮动
toolBar->setFloatable(false);
//设置移动
toolBar->setMovable(false);
//工具栏添加控件
QPushButton * btn = new QPushButton("按钮",this);
toolBar->addWidget(btn);
// 工具栏中添加菜单项
toolBar->addAction(newAction);
//分割线
toolBar->addSeparator();
toolBar->addAction(openAction);
/*************************工具栏 可以有多个 *************************/
/*************************状态栏 只能有一个 *************************/
QStatusBar * status = statusBar();
//状态栏放入窗口中
setStatusBar(status);
//添加标签控件
QLabel * label = new QLabel("左侧信息",this);
//将标签放入状态栏 从左往右
status->addWidget(label);
QLabel * label1 = new QLabel("右侧信息",this);
//从右往左放
status->addPermanentWidget(label1);
/*************************状态栏 只能有一个 *************************/
/*************************铆接部件(浮动窗口) 可以有多个 *************************/
QDockWidget *dock = new QDockWidget("铆接部件",this);
//放入窗口
addDockWidget(Qt::TopDockWidgetArea,dock);
//设置停靠范围
dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
/*************************铆接部件(浮动窗口) 可以有多个 *************************/
/*************************核心部件 只能有一个 *************************/
QTextEdit * edit = new QTextEdit(this);
//设置核心部件
setCentralWidget(edit);
/*************************核心部件 只能有一个 *************************/
}
9. 资源文件的添加
- 将资源文件夹放到项目文件夹中
- 右键项目名-新建文件-Qt-资源文件
- 添加前缀-添加文件-将资源文件全选添加
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//在新建的菜单项上 显示图片
//ui->actionnew->setIcon(QIcon("C:/Users/ShuaiZheng/Pictures/Saved Pictures/favicon.ico"));
//资源文件的使用 ":+ 前缀名 + 文件名"
//前缀名可以不用/,可以用分类取名
ui->actionnew->setIcon(QIcon(":/Image/favicon.ico"));
}
10. 对话框
10.1 模态和非模态对话框
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDebug>
#include<QDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//点击新建,弹出对话框
connect(ui->actionnew,&QAction::triggered,[=](){
qDebug() << "弹出对话框";
//对话框分类
//模态对话框(不可以对其他窗口进行操作) 非模态对话框(可以对其他窗口进行操作)
//模态创建
QDialog * dialog = new QDialog(this); // QDialog dialog(this);创建在栈上
dialog->resize(200,100);
dialog->exec(); //模态创建(阻塞)
qDebug() << "模态对话框弹出了";
});
connect(ui->actionopen,&QAction::triggered,[=](){
//非模态
QDialog * dialog1 = new QDialog(this);
dialog1->show();
dialog1->resize(200,100);
dialog1->setAttribute(Qt::WA_DeleteOnClose); //55号 属性,点叉释放变量
qDebug() <<"非模态对话框创建了";
});
}
10.2 消息对话框
connect(ui->actionmessage,&QAction::triggered,[=](){
//错误对话框
// QMessageBox::critical(this,"critical","错误");
//信息对话框
//QMessageBox::information(this,"information","信息");
//提问对话框
//参数1——父亲 参数2——标题 参数3——提示内容 参数4——按键类型 参数5——默认关联回车的按键
// if(QMessageBox::Save == QMessageBox::question(this,"question","提问",QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Cancel))
// {
// qDebug() << "选择的是保存";
// }
// else
// {
// qDebug() << "选择的是取消";
// }
//警告对话框
//QMessageBox::warning(this,"warning","警告");
//颜色对话框
// QColor color= QColorDialog::getColor(QColor(255,0,0));
// qDebug() << "r = " << color.red() << "g = " << color.green() << "b = " << color.blue();
//文件对话框 参数1——父亲 参数2——标婷 参数3——默认打开路径 参数4——过滤文件格式
//返回值是 选取文件的路径
// QString str = QFileDialog::getOpenFileName(this,"打开文件","C:/Users/ShuaiZheng/Desktop","*.txt");
// qDebug() << str;
//字体对话框
bool flage;
QFont font = QFontDialog::getFont(&flage,QFont("宋体",36));
qDebug() << "字体:" << font.family().toUtf8().data() << "字号:" << font.pointSize() << "是否加粗:" << font.bold()
<< "是否倾斜:" << font.italic();
});
11. 界面布局
- 选取
widget
进行布局,水平布局,垂直布局,栅格布局 - 可以加水平和垂直弹簧
- 默认窗口和控件有9 间隙,可调
- edit可以设置格式,
echoMode
有 normal,noecho,password和passwordechoon这四种模式
12.控件
12.1 按钮组
QPushButton
常用按钮QToolButton
工具按钮 —— 用于显示图片和文字toolButtonstyle
——凸起风格autoralse
radioButton
单选按钮,设置默认setchecked(true)
checked
多选按钮,监听状态,&QCheckBox::stateChanged
,2是选中 0是未选中 1半选状态
12.2 QListWidget 列表容器
QListWidgetItem * item = new QListWidgetItem("锄禾日当午")
一行内容ui->objectname->additem(item)
- 设置居中
item->setTextAlignment(Qt::AlignHCenter)
- 可以用
QStringList
进行多行赋值
QStringList list;
list << "锄禾日当午" << "汗滴禾下土" << "谁知盘中餐" << "粒粒皆辛苦";
ui->listWidget->addItems(list);
12.3 QTreeWidget树控件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//treewidget树控件使用
//设置水平头
ui->treeWidget->setHeaderLabels(QStringList()<<"英雄" << "英雄简介");
QTreeWidgetItem * PowerItem = new QTreeWidgetItem(QStringList()<< "力量");
//加载顶层节点
ui->treeWidget->addTopLevelItem(PowerItem);
//追加子节点
QTreeWidgetItem * PowerItem_s1 = new QTreeWidgetItem(QStringList()<< "刚背猪" << "前排坦克");
PowerItem->addChild(PowerItem_s1);
QTreeWidgetItem * AgileItem = new QTreeWidgetItem(QStringList()<< "敏捷");
//加载顶层节点
ui->treeWidget->addTopLevelItem(AgileItem);
//追加子节点
QTreeWidgetItem * AgileItem_s1 = new QTreeWidgetItem(QStringList()<< "月骑" << "中排物理输出");
AgileItem->addChild(AgileItem_s1);
QTreeWidgetItem * IntelligenceItem = new QTreeWidgetItem(QStringList()<< "智力");
//加载顶层节点
ui->treeWidget->addTopLevelItem(IntelligenceItem);
//追加子节点
QTreeWidgetItem * IntelligenceItem_s1 = new QTreeWidgetItem(QStringList()<< "巫灵法师" << "前排坦克法师");
IntelligenceItem->addChild(IntelligenceItem_s1);
}
12.4 QTableWidget
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//tablewidget控件
//先设置列数
ui->tableWidget->setColumnCount(3);
//设置表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名" << "性别" << "年龄");
//设置行数
ui->tableWidget->setRowCount(5);
//添加数据
//ui->tableWidget->setItem(0,0,new QTableWidgetItem("亚瑟"));
QStringList namelist , sexlist , agelist; //QList<QString> namelist , sexlist , agelist;
namelist << "亚瑟" << "赵云" << "张飞" << "关羽" << "花木兰";
sexlist << "男" << "男" << "男" << "男" << "女";
agelist << "21" << "25" << "26" << "31" << "18";
for(int i = 0; i < 5;i++)
{
int col = 0;
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(namelist[i]));//[]越界程序崩溃
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexlist.at(i)));//at越界抛出异常
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(agelist[i]));
//ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
//int 转 QString
}
}
12.5 其他常用控件介绍
scroll Area
滚动区域Tool Box
类似QQ的分组tab widget
类似网页stacked widget
切换显示——需要用按钮来点击切换到哪一页
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//栈控件的使用
//设置默认定位scrollArea
ui->stackedWidget->setCurrentIndex(0);
//scrollArea按钮
connect(ui->scrollArea_Btn,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(0);
});
//TabWidget按钮
connect(ui->TabWidget_btn,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(1);
});
//TollBox按钮
connect(ui->TollBox_btn,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(2);
});
}
comboBox
下拉框- ‘Qlabel’ 显示文字、图片、动图
//下拉框
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("玛莎拉蒂");
ui->comboBox->addItem("宝马");
//点击按钮 选中拖拉机选项
connect(ui->btn1,&QPushButton::clicked,[=](){
//ui->comboBox->setCurrentIndex(2);
ui->comboBox->setCurrentText("玛莎拉蒂");
});
//Qlabel添加图片
ui->label->setPixmap(QPixmap(":/image/favicon.ico"));
//利用label显示 gif动图
QMovie * movie = new QMovie(":/image/mario.gif");
ui->label_2->setMovie(movie);
//播放动图
movie->start();
13.自定义控件封装
- 添加新文件——Qt——设计师界面类
- ui中设计 QSpinBox和QSlider 两个控件组合
- widget中使用自定义控件:拖拽widget,右键提升为,输入自定义控件类名
- 实现功能,改变数字,滑动条跟着移动
- 提供getNum和setNum的对外接口
#include "smallwidget.h"
#include "ui_smallwidget.h"
SmallWidget::SmallWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::SmallWidget)
{
ui->setupUi(this);
//QSpinBox移动 QSlider跟着移动
//函数指针
void(QSpinBox:: * spSignal)(int) = &QSpinBox::valueChanged;
connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
//QSlider移动 QSpinBox数字跟着变化
connect(ui->horizontalSlider,&QSlider::sliderMoved,ui->spinBox,&QSpinBox::setValue);
}
//设置数字
void SmallWidget::setNum(int num)
{
ui->spinBox->setValue(num);
}
//获取数字
int SmallWidget::getNum()
{
return ui->spinBox->value();
}
SmallWidget::~SmallWidget()
{
delete ui;
}
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击获取按钮 获取当前值
connect(ui->GetNumBtn,&QPushButton::clicked,[=](){
qDebug() << ui->smallWidget->getNum();
});
//点击按钮设置值
connect(ui->SetNumBtn,&QPushButton::clicked,[=](){
ui->smallWidget->setNum(50);
});
}
Widget::~Widget()
{
delete ui;
}