一、认识QT
1.1 QT的优点
- 跨平台
- 接口简单,容易上手
- 一定程度上简化了内存回收
1.2 QT的基类
- QtCreator默认创建窗口类,基类有三种选择:
QWidget
、QMainWindow
、QDialog
- main函数:
QApplication a;
应用程序对象,有且只有一个Widget w;
实例化窗口对象w.show();
调用show函数显示窗口return a.exec();
让应用程序进入消息循环机制中,代码阻塞到当前行1.3 命名规范和快捷键
1.3.1 命名规范
- 类名 首字母大写,单词和单词之间的首字母大写,驼峰命名法
- 函数名 变量名称 首字母小写,单词和单词之间首字母大写,首字母为小写的驼峰命名法
1.3.2 快捷键
- ctrl + b 编译
- ctrl + r 运行
- ctrl + i 自动对齐
- CTRL + shift + ↑ 或者 ↓ 整行移动
- 同名之间的.cpp和.h文件切换 F4
- 帮助页面 F1 或者 左侧的按钮 或者 直接打开文档 (在安装路径/mingw/bin中)
1.4 创建一个按钮
1.4.1 根据原有的类创建按钮
```Cpp #include “widget.h” #include “QPushButton” // 引入按钮类
Widget::Widget(QWidget *parent) : QWidget(parent) // 初始化列表 { // 创建第一个按钮 QPushButton *btn1 = new QPushButton(); // 按钮显示在窗口里 btn1->setParent(this); // 设置按钮中的字 btn1->setText(“第一个按钮”);
// 创建第二个按钮,会使窗口自适应控件大小
QPushButton *btn2 = new QPushButton("第二个按钮", this);
// 移动第二个按钮的位置
btn2->move(0, 50);
// 设置窗口大小
resize(600, 400);
// 固定窗口的大小
setFixedSize(600, 400);
// 设置窗口标题
setWindowTitle("第一个测试案例"); }
// 析构函数 Widget::~Widget() {}
##### 1.4.2 创建自己的按钮类
###### 1.4.2.1 按钮的头文件
```Cpp
#pragma once
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QPushButton>
#include <QWidget>
class MyButton : public QPushButton
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
signals:
};
#endif // MYBUTTON_H
1.4.2.2 按钮的Cpp源文件
#include "mybutton.h"
MyButton::MyButton(QWidget *parent)
: QPushButton{parent}
{}
1.4.2.3 按钮在窗口中的实现
MyButton *mybtn = new MyButton;
mybtn->setParent(this);
mybtn->move(100, 0);
mybtn->setText("我自己的按钮");
1.5 对象树
当创建的对象在堆区的时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作,将对象会放入到对象树中,在父类析构函数执行的时候会释放所有对象树中的子类,在一定程度上简化了内存回收机制
1.6 坐标系
- 左上角的坐标系为(0,0)
- x以右为正方向,y以下为正方向
1.7 信号和槽
1.7.1 信号和槽的使用方法
connect
函数参数:- 信号( signal )的发送者
- 发送的具体信号:&函数的地址
- 信号的接受者
- 信号的处理(槽 slot):&函数的地址
- 信号槽的优点:松散耦合,信号发送端和接收端本身是没有关联的,通过
connect
将两者耦合在一起
函数实现:
connect(mybtn, &MyButton::clicked, this, &Widget::close);
1.7.2 自定义的信号和槽
1.7.3 Lambda表达式
- 值的引用
[=](){};
:函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda
所在类中的this
),并且是值传递方式
;[&](){};
:函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda
所在类中的this
),并且是引用传递方式
;[this](){};
:函数体内可以使用Lambda
所在类中的成员变量;[a](){};
:将a按值进行传递,函数体内不能修改传递进来的a
的拷贝,因为默认情况下函数是const
的,如果需要修改传递进来的a
的拷贝,可以添加mutable
修饰符;[&a](){};
:将a
按引用进行传递;[= ,&a, &b](){};
除了a
和b
按引用传递外,其他参数按值传递;[& ,a, b](){};
除了a
和b
按值传递外,其他参数按引用传递;- 也可以是空,什么参数都不用;
- 操作符重载函数参数
标识重载的
()
操作符的参数,没有参数时,这部分可以省略。参数可以通过按值和按引用进行传递; - 可修改标识符
mutable
声明,可以修改拷贝,不可以修改本体int a = 10; connect(mybtn, &QpushButton::clicked, this, [m]()mutable{ m = 100 + 10; qDebug() << m;}); // 输出不会变 qDebug() << m;
- 返回值
[]()->int{return a};
- 函数体
{} 可以空但是不可以省略
- 一般使用值传递,引用传递可能会出现一些bug
- 如果使用Lambda表达式,this参数可以省略
connect(btn, &QPushButton::clicked, [=](){ this->close();});
1.8 练习
- 要求:一个窗口两个按钮,一个
open
,一个close
,使用open打开新窗口,使用close关闭新窗口; - 升级版:一个按钮,初始化为
open
按钮,打开新窗口之后变成close
。 ```Cpp #include “widget.h” #include “QPushButton”
Widget::Widget(QWidget *parent) : QWidget(parent) { QPushButton *btn1 = new QPushButton; btn1->setParent(this); btn1->setText(“open”);
QPushButton *btn2 = new QPushButton;
btn2->setParent(this);
btn2->move(100, 0);
btn2->setText("close");
QWidget *myWindow = new QWidget;
myWindow->setWindowTitle("这是一个弹出窗口");
connect(btn1, &QPushButton::clicked, myWindow, [=]() {
if (btn1->text() == "open") {
btn1->setText("close");
myWindow->show();
}
else {
btn1->setText("open");
myWindow->close();
}
});
connect(btn2, &QPushButton::clicked, myWindow, [=]() {
myWindow->close();
}); }
Widget::~Widget() { } ```
二、QMainWindow
2.1 主页面控件
- 菜单栏最多有一个
- 工具栏可以有多个
- 状态栏最多有一个
- 铆接部件(浮动窗口)可以有多个
- 中心部件只能有一个
- 只能有一个的设置以set开头,可有多个的设置以add开头
2.2 资源文件添加
- setIcon()
2.3 模态和非模态对话框创建
- 模态对话框:不可以对其他窗口进行操作
- QDialog dlg(this)
- dlg.exec() - 非模态对话框:可以对其他窗口进行操作
- QDialog *dlg = new QDialog(this);
- dlg->show();
- dig->setAttribute(Qt::WA_DeleteOnClose);//55号
2.4 标准对话框创建
- 消息对话框 QMessegeBox静态对象创建
- 参数列表:
- 参数1 父亲
- 参数2 标题
- 参数3 显示内容
- 参数4 按键类型
- 参数5 默认关联回车键内容
- critical
- information
- question
- waring - 其他标准对话框
- 颜色对话框 QColorDialog
- getColor(QColor(255, 0, 0));
- 返回值是QColor
- 成员函数 red() blue() green()
- getColor(QColor(255, 0, 0));
- 文件对话框 QFileDialog
- getOpenFileName
- 参数1 父亲
- 参数2 窗口标题显示内容
- 参数3 文件路径
- 参数4 过滤文件(*.txt)
- 返回值为QString,选取的路径
- getOpenFileName
- 字体对话框 QFontDialog
- getFont(&flag, QFont(“华云彩文”, 36));
- 参数1 布尔值
- 参数2 字体
- 返回值为QFont
- 成员函数 family() pointSize() bold() italic()
2.5 登录窗口布局
2.6 控件 - 控件组
- QPushButton
- QToolButton 工具按钮 显示图片 autoRaise toolButtonStyle
- radioButton 单选按钮
- getFont(&flag, QFont(“华云彩文”, 36));
- 默认选中 setChecked()
- checkBox 多选按钮 0 未选中 1 半选中 2 选中
2.7 QListWidget
- QListWidgetItem类 - addItem成员函数添加 - setTextAlignMent() 设置格式 - `QStringList QList<QString>`
- QStringList list;
- list « “1” « “2” « “3” « “4”;
- addItems(list);
2.8 QTreeWidget
- 只能有一个的设置以set开头,可有多个的设置以add开头
- 设置头
- setHeaderLabels
- 创建根节点
- QTreeWidgetItem *strengthItem = new QTreeWidgetItem(QSTringList() «“英雄” « “英雄介绍”)
- 添加根节点到树控件
- treeWidget->addTopLevelItem(strengthItem);
- 添加子节点
- addChild(childNode)
2.10 QTableWidget
- addChild(childNode)
- 设置列数 setColumnCount
- 设置水平表头 姓名 性别 年龄 setHorizontableHeaderLables
- 设置行数 setRowCount
- 设置正文
setItem(i, j, new QTableWidgetItem())
2.9 其他控件
- stackWidget->setCurrentIndex()
- comboBox->addItem()
- label->setPixmap()
- lable->setMovie(movie)
- movie->start
三、其他基础知识
3.1 自定义封装控件
- 添加新文件 -> 设计师界面类
- 拖拽一个widget,点击添加、提升,将widget控件升级为自定义控件
- QSpinBox 改变数值,QSlider 跟着动
- QSlider 拉动, QSpinBox 跟着改变数值
3.2 QEvent
- 鼠标进入事件 enterEvent
- 鼠标离开事件 leaveEvent
- 鼠标按下 mousePressEvent(QMouseEvent ev)
- 鼠标释放 mouseReleaseEvent
- 鼠标移动 mouseMoveEvent
- ev->x()/y()/globalx()/globaly()
- ev->button() 可以判断所有按键 Qt::LeftButton
- ev->buttons() 可以判断组合按键 判断move时候的左右键 结合&操作符
- 格式化字符串 QString(“%1 %2).arg(111).arg(222)
- 设置鼠标跟踪 setMouseTracking(true)
3.3 定时器1
- 利用事件 void timerEvent(QTimerEvent *ev)
- 启动定时器 startTimer(1000)毫秒单位
- timerEvent 的返回值是定时器的唯一标识 可以和 ev->timerId 作比较
3.4 定时器2
- 定时器类 QTimer
- 创建定时器对象
- 启动定时器 timer->start()
- 每隔一定毫秒,发送信号 timeout,进行监听
- 暂停,timer->stop()
3.5 事件分发器
- 用于事件的分发:event()
- 也可以做事件的拦截,不建议
- if(e->type == QEvent::MouseButtonPress) 若return的为true则用户自己处理该事件
3.6 事件过滤器
- 在程序分发到event事件之前再做一次高级拦截
- 给控件安装事件过滤器
- 重写eventfilter事件
- ui->label->installEventFilter(this);
3.7 绘图事件
- 重写paintEvent
- 包含
<Qpainter>
- 声明一个画家对象 QPainter painter(this) this指定绘图设备
- 画线、画圆、画矩形、画文字
- QPen 设置笔的风格
- QBrush 设置笔刷填充
3.8 绘图高级设置
- 设置抗锯齿 setRenderHint 效率低
- painter.translate() 移动画家的位置
- painter.save() 保存画家状态
- painter.restore() 重置画家状态
3.9 手动调用绘图事件
- QPainter painter(this);
- painter.drawPixmap(20, 100, QPixmap(“:/Image/luffy.png”));
- 手动调用repaint() update()
3.9 绘图设备
- 绘图设备是指继承QPainterDevice的子类。Qt一共提供了四个这样的类,分别是QPainter、QBitmap、QImage、QPicture
- QPainter专门为图像在屏幕上的显示做了优化
- QBitmap是QPixmap的一个子类,它的色深限定为1,可以使用QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QPixmap
- QImage专门为图像的像素级访问做了优化
- QPicture可以记录和重现QPainter的各条命令
- setPicture(i, j, value);
- painter.begin(&pic)
3.9 QFile实现对文件的读写
- QTextCodec 编码格式类 QTextCodec *codec = new QTextCodec::codecForName(“gbk)
- codec->toUnicode(array)
3.9 QFile实现对文件信息的读取
- info.size()/suffix()/path()/created()/created().toString(“yyyy-MM-dd hh:mm:ss)
四、翻金币小游戏案例
4.
- 打包 windeployqt name.exe