Qt基础

Posted by LemonWhale on May 22, 2024

一、认识QT

1.1 QT的优点

  • 跨平台
  • 接口简单,容易上手
  • 一定程度上简化了内存回收

    1.2 QT的基类

  • QtCreator默认创建窗口类,基类有三种选择:QWidgetQMainWindowQDialog
  • 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函数参数:
    1. 信号( signal )的发送者
    2. 发送的具体信号:&函数的地址
    3. 信号的接受者
    4. 信号的处理(槽 slot):&函数的地址
  • 信号槽的优点:松散耦合,信号发送端和接收端本身是没有关联的,通过connect将两者耦合在一起

函数实现

connect(mybtn, &MyButton::clicked, this, &Widget::close);
1.7.2 自定义的信号和槽
1.7.3 Lambda表达式
  1. 值的引用
    • [=](){};:函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类中的this),并且是值传递方式
    • [&](){};:函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类中的this),并且是引用传递方式
    • [this](){};:函数体内可以使用Lambda所在类中的成员变量;
    • [a](){};:将a按值进行传递,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的,如果需要修改传递进来的a的拷贝,可以添加mutable修饰符
    • [&a](){};:将a按引用进行传递;
    • [= ,&a, &b](){};除了ab按引用传递外,其他参数按值传递;
    • [& ,a, b](){};除了ab按值传递外,其他参数按引用传递;
    • 也可以是空,什么参数都不用;
  2. 操作符重载函数参数 标识重载的()操作符的参数,没有参数时,这部分可以省略。参数可以通过按值和按引用进行传递;
  3. 可修改标识符 mutable声明,可以修改拷贝,不可以修改本体
     int a = 10;
     connect(mybtn, &QpushButton::clicked, this, [m]()mutable{ m = 100 + 10; qDebug() << m;});
     // 输出不会变
     qDebug() << m;
    
  4. 返回值 []()->int{return a};
  5. 函数体 {} 可以空但是不可以省略
    • 一般使用值传递,引用传递可能会出现一些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 主页面控件

  1. 菜单栏最多有一个
  2. 工具栏可以有多个
  3. 状态栏最多有一个
  4. 铆接部件(浮动窗口)可以有多个
  5. 中心部件只能有一个
    • 只能有一个的设置以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. 参数1 父亲
      2. 参数2 标题
      3. 参数3 显示内容
      4. 参数4 按键类型
      5. 参数5 默认关联回车键内容
    • critical
    • information
    • question
    • waring - 其他标准对话框
    • 颜色对话框 QColorDialog
      • getColor(QColor(255, 0, 0));
        • 返回值是QColor
      • 成员函数 red() blue() green()
    • 文件对话框 QFileDialog
      • getOpenFileName
        • 参数1 父亲
        • 参数2 窗口标题显示内容
        • 参数3 文件路径
        • 参数4 过滤文件(*.txt)
        • 返回值为QString,选取的路径
    • 字体对话框 QFontDialog
      • getFont(&flag, QFont(“华云彩文”, 36));
        • 参数1 布尔值
        • 参数2 字体
        • 返回值为QFont
      • 成员函数 family() pointSize() bold() italic()

        2.5 登录窗口布局

        2.6 控件 - 控件组

        • QPushButton
        • QToolButton 工具按钮 显示图片 autoRaise toolButtonStyle
        • radioButton 单选按钮
    • 默认选中 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

  6. 设置头
    • setHeaderLabels
  7. 创建根节点
    • QTreeWidgetItem *strengthItem = new QTreeWidgetItem(QSTringList() «“英雄” « “英雄介绍”)
  8. 添加根节点到树控件
    • treeWidget->addTopLevelItem(strengthItem);
  9. 添加子节点
    • addChild(childNode)

      2.10 QTableWidget

  10. 设置列数 setColumnCount
  11. 设置水平表头 姓名 性别 年龄 setHorizontableHeaderLables
  12. 设置行数 setRowCount
  13. 设置正文 setItem(i, j, new QTableWidgetItem())

    2.9 其他控件

  14. stackWidget->setCurrentIndex()
  15. comboBox->addItem()
  16. label->setPixmap()
  17. lable->setMovie(movie)
  18. 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事件之前再做一次高级拦截
    1. 给控件安装事件过滤器
    2. 重写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