QT入门到实战学习笔记

学习笔记 

最新QT从入门到实战完整版|传智教育_哔哩哔哩_bilibili

目录

 1.创建一个QT文件

1.1命名规范

1.2快捷键 

2QPushButton创建

2.1防止汉语乱码 

2.2对象树

 2.3Qt窗口坐标体系

 3信号和槽机制

 3.1自定义信号和槽

 3.1.1自定义信号:

3.1.2自定义槽:

3.2自定义信号和槽发生重载

 3.2.1重载:

 3.2.2连接解决办法:

3.2.3QString输出的内容带引号解决办法:

3.3信号槽的拓展

3.3.1无参信号和槽连接

3.3.2信号连接信号

3.3.3断开信号:disconnect

 3.3.4一个信号可以连接多个槽函数

 3.3.5多个信号可以连接同一个槽函数

3.3.6信号和槽函数的参数必须一一对应

3.3.7信号的参数个数可以比槽函数参数个数多,但是需要一一对应,反之不可

3.4Lambda表达式 

3.5Open Close控制实现案例

4.QMainWindow

 4.1菜单栏:

4.2工具栏:

 4.3状态栏:

4.4铆接部件(浮动窗口):

4.5中心部件: 

4.6全部代码 

4.7资源文件添加

5.对话框

5.1自定义消息框 

5.1.1模态创建: 

 5.1.2非模态创建:

 5.2标准对话框

 5.2.1QMessageBox下的四种对话框:

5.3其他标准对话框

 5.3.1颜色对话框:

5.3.2文件对话框:

5.3.3字体对话框: 

5.4全部代码

6.界面布局

 7.控件

 7.1按钮组

 7.2QListWidget 列表容器

 7.3QTreeWidget 树控件

  7.4QTableWidget 表格控件

7.5自定义封装控件

1.添加新文件->QT->设计师界面类

 2.在新建的.ui文件中设置QSpinBox和QSlider两个控件

 3.在widget.ui中使用自定义的控件

 4.联动效果

5.提供接口,获取数字和设置数字

8.QT中的鼠标事件

8.1鼠标进入事件enterEvent

 8.1.1在mylabel.h头文件中添加声明

8.1.2在mylabel.cpp文件中设置函数体

8.2鼠标离开事件leaveEvent

8.2.1在mylabel.h中添加声明

8.2.2在mylabel.cpp文件中设置函数体

8.3.鼠标按下   鼠标释放  鼠标移动 

8.3.1 mylabel.h中声明

8.3.2  ev->x()  ev->y()       x坐标,y坐标

8.3.3  ev->button()        判断左右键 

8.3.4  ev->buttons()        判断组合按键   

判断move时候的左右键  结合与操作符

8.3.5 设置鼠标追踪 

8.3.6 mylabel.cpp中写函数体

8.3.7格式化字符串   

9.定时器、分发器、过滤器、绘图

9.1定时器的第一种方式 

9.1.1利用事件 void timerEvent(QTimerEvent *ev)

9.1.2启动定时器 startTimer() 毫秒单位

9.1.3timerEvent的返回值是定时器的唯一标识

9.2定时器的第二种方式

9.2.1利用定时器的类  QTimer 

 9.2.2创建定时器对象

 9.2.3启动定时器 timer->start

9.2.4信号槽连接 

9.2.5暂停  timer->stop

9.3 事件分发器event

9.3.1  bool event(QEvent * e)

9.3.2  返回值若是true,则代表用户处理这个时间,不向下分发了

9.3.3   e->type() 可以判断事件

9.4事件过滤器

9.4.1给控件安装事件过滤器

9.4.2重写eventFilter(obj,e)函数

9.5 QPainter绘图

 9.5.1绘图事件  void paintEvent

9.5.2声明一个画家对象

 9.5.3画图、画文字、设置风格等

9.6  QPainter 高级设置

9.6.1抗锯齿操作  (效率较低)

9.6.2对画家进行移动

 9.6.3保存画家状态

9.6.4还原状态

9.7手动调用绘图事件

9.7.1 Using the painter to draw pictures

 9.7.2 Use update to manually call the drawing event

9.8 QPaintDevice drawing device

9.8.1QPixmap

9.8.2QImage

9.8.3QPicture

10 QFile Read and write operations on files

 10.1 Reading files

 10.1.1 Signal slot connection button and file

10.1.2 Put the path in lineEdit 

10.1.3 Read file format

10.1.4 Opening files in read-only mode

10.1.5 Reading files

10.1.6 File Trailer

10.1.7 Put the read data into the text box

10.1.8 Need to convert format to read

10.1.9 Closing the file

10.2 Writing files

10.3 All codes for reading and writing files

 10.4 QFlieInfo read file information

11 Cases of Flipping Gold Coins

11.1 Create a project and add resource configuration

11.2 Project Configuration Settings Background Size Title Background Icon 

11.2.1 Configure size, icon, title, exit button

11.2.2 Configuration background 

11.3 Creating the start button

       11.3.1 Encapsulating a custom button MyPushButton

        11.3.2 Constructor (the picture is displayed by default, and the picture is displayed after pressing)

        11.3.3 Start making special effects zoom1, zoom2

11.4 Create a selection level scene

        11.4.1 After clicking the start button, enter the selected level scene with a delay

       11.4.2 Configure the selected level scene (set the background size and title background icon) 

        11.4.3 Creating the back button

         11.4.4 Return button special effect switching of the return level

11.4.5 Switching between the start scene and the selected level scene

11.5 Select level button creation

11.5.1 Creating a matrix with a single for loop 

 11.5.2 Set the number of levels displayed on the button

11.6 Basic configuration of gold coin flipping scene

11.6.1 Configure the game scene (set the background size title background icon) 

11.6.2 Implement the back button to return to the previous scene 

11.6.3 Realize the label of the display level

 11.7 Create a gold coin class

 11.7.1 First put the background pattern of gold coins into PlayScene

11.7.2 Create MyCoin custom gold coin button class

11.7.3 Create all gold coin buttons in playscene

11.8 The default display of each level

11.9 Flip gold coin effects

 11.9.1 Add attribute posx posy bool flag to each coin

11.9.2 Add function to MyCoin

11.9.3 Listening to Signals and Flipping

11.9.4 Solve the problem that the fast click effect is not good

11.9.5 Click around the coin to flip it together

11.9.6 Determining Victory

11.9.7 Victory Picture Settings

11.9.8 Sound Effect Settings

11.9.9 Keeping a position per scene

 11.10 Project packaging and game expansion


 1. Create a QT file

  •  Click to create a project, select the project path and name (cannot contain Chinese)
  •  There are window classes created by default, and there are three options for the base class: Qwidget, QmyWindow, QDialog.main.cpp Introduction
  • main function: see comments
#include "widget.h"

#include <QApplication>//包含一个应用程序类的头文件
#include <QLocale>
#include <QTranslator>


//main程序入口,argc命令行变量的数量,argvming命令行变量的数组
int main(int argc, char *argv[])
{
    //a 应用程序对象,在Qt中,应用程序对象,有且只有一个
    QApplication a(argc, argv);

    QTranslator translator;
    const QStringList uiLanguages = QLocale::system().uiLanguages();
    for (const QString &locale : uiLanguages) {
        const QString baseName = "test01_" + QLocale(locale).name();
        if (translator.load(":/i18n/" + baseName)) {
            a.installTranslator(&translator);
            break;
        }
    }
    //窗口对象
    Widget w;
    //窗口对象,默认不会显示,必须要调用show方法显示窗口
    w.show();

    //让应用程序对象 a 进入消息循环机制,让代码停留在这行
    return a.exec();
}

1.1 Naming convention

Class name: capitalize the first letter, capitalize the first letter between words and words

Function name variable name: the first letter is lowercase, and the first letter between words is capitalized

1.2 shortcut keys 

Note: ctrl + /

Run: ctrl + r

Compile: ctrl + b

Font scaling: ctrl + mouse wheel

Find: ctrl + f

Move the whole line: ctrl + shift + ↑ or ↓

Help documentation: F1        

Automatic alignment: ctrl + i

Toggle between .h and .cpp with the same name: f4

2QPushButton creation

 Create QPushButtn *btn = new QPushButton

set parent  setParent(this)

Set the text    setText("text")

Set position    move (width, height)

Re-specify the window size  resize

Set the window title    setWindowTitle("window");

Set the fixed window size    setFixedSize(600,600);

 mainwindow.cpp

#include "mainwindow.h"
#include<QPushButton>//按钮头文件
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    //创建一个按钮
    QPushButton *btn = new QPushButton;
    //btn->show();//show以顶层方式弹出控件
    btn->setParent(this);

    //重新制定按钮大小
    btn->resize(100,100);

    //显示文本
    btn->setText("first");

    //创建第二个按钮  按照控件大小创建窗口
    QPushButton *btn2=new QPushButton("second",this);

    //移动btn2按钮
    btn2->move(100,100);

    //重置窗口大小
    resize(800,800);

    //设置窗口标题
    setWindowTitle("窗口");

    //设置固定窗口大小
    setFixedSize(600,600);
}

MainWindow::~MainWindow()
{
}

2.1 Prevent Chinese garbled characters 

Which file needs it, just add this line of code above it 

#pragma execution_character_set("utf-8")//Prevent garbled characters

 Open Options -> Text Editor -> Behavior, as shown in the figure

 Open Edit->select enconding and set as shown in the figure

 

2.2 Object tree

 When the created object is re-heaped, if the specified parent is a class derived from Qobject or a class derived from a Qobject subclass, the object can be put into the object tree without managing the release operation.

To a certain extent, the memory recovery mechanism is simplified

 2.3Qt window coordinate system

 With the upper left corner as the far point (0, 0), X increases to the right and Y increases downward

 3 signal and slot mechanism

connect(sender, signal(function address), receiver, slot function)

connect(  mybtn  ,  &QPushButton::clicked  ,  this  ,  &MainWindow::close  );

 3.1 Custom signals and slots

Customize teacher->hungry->student->treat guests to dinner (hungry is a signal, eating is a slot)

Create teacher and student classes (Teacher;Student) -> header file declaration -> source file slot function implementation

When the header file declares:

 3.1.1 Custom signal:

        Custom signal, written under signals,
        the return value is void, only need to declare, no need to implement,
        can have parameters, can be overloaded

signals:
    void hungry();

3.1.2 Custom slot:

        Early versions of qt must be written to public slots, and advanced versions can be downloaded to public or global functions

        The return value is void, which needs to be declared and implemented

        Can have parameters, overloading can occur

public slot:
    void treat();

 > Slot function implementation of the source file

void Student::treat()
{
    qDebug()<<"请老师吃饭";
}

 Widget.cpp file:

Widget::Widget(QWidget *parent): QWidget(parent)
{
 //创建一个老师的对象
    this->zt=new Teacher(this);
    //创建一个学生的对象
    this->st=new Student(this);
    //老师饿了 学生请客吃饭连接
    connect(zt,&Teacher::hungry,st,&Student::treat);
    //调用下课函数
    classIsOver();//有顺序的,需要先连接再调用
}

void Widget::classIsOver()
{
    //下课函数,调用后,老师饿了
    emit zt->hungry();//触发的关键字:emit
}
void Widget::classIsOver()
{
    //下课函数,调用后,老师饿了
    //emit zt->hungry();//触发的关键字:emit
    emit zt->hungry("烤腰子");
}

 The keyword that triggers the signal: emit 

3.2 Custom signals and slots are overloaded

 3.2.1 Overloading:

In the teacher.h file:

signals:
    void hungry();
    void hungry(QString foodNname);

 In the student.h file:

public slot:
    void treat();
    void treat(QString foodName);

 Slot function (students treat guests to dinner) implementation:

void Student::treat(QString foodName)
{
    qDebug()<<"请老师吃饭,老师要吃:"<<foodName;
}

 3.2.2 Connection solution:

 Need to use the function pointer to clearly point to the address of the function

    void(Teacher::*teacherSignal)(QString)=&Teacher::hungry;
    void(Student::*studentSlot)(QString) = &Student::treat;
    connect(zt,teacherSignal,st,studentSlot);//有参

3.2.3 QString output content with quotation marks solution:

qDebug()<<"请老师吃饭,老师要吃:"<<foodName;

 

Solution: 

QString->char* is first converted to QByerArray(.toUtf8()) and then converted to char*()
qDebug()<<"请老师吃饭,老师要吃:"<<foodName.toUtf8().data();

3.3 Expansion of signal slots

 Set it up: click a button to trigger the get out of class dismissal signal

QPushButton *btn=new QPushButton("下课",this);
connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);//按钮->触发->下课

3.3.1 No-argument signal and slot connections

    void(Teacher::*teacherSignal2)(void)=&Teacher::hungry;
    void(Student::*studentSlot2)(void) = &Student::treat;
    connect(zt,teacherSignal2,st,studentSlot2);

3.3.2 Signal connection signal

(button -> teacher is hungry -> student treat)

    connect(zt,teacherSignal2,st,studentSlot2);
    connect(btn,&QPushButton::clicked,zt,teacherSignal2);

3.3.3 Disconnect signal: disconnect

disconnect(zt,teacherSignal2,st,studentSlot2);

 3.3.4 A signal can be connected to multiple slot functions

    connect(btn,&QPushButton::clicked,zt,teacherSignal2);
    connect(btn,&QPushButton::clicked,this,&Widget::close);

 3.3.5 Multiple signals can be connected to the same slot function

3.3.6 The parameters of signal and slot functions must correspond one by one

3.3.7 The number of parameters of the signal can be more than the number of parameters of the slot function, but it needs to correspond one by one, and vice versa

3.4 Lambda expressions 

[](){};

    [=](){
        btn->setText("放学");
    }();

 [] is the beginning of Lambda, it must exist and cannot be omitted

In square brackets:

= : pass by value;         & : pass by reference;         this : similar to =;         a : pass a by value;

&a : pass a by reference;                 & , a , b : pass by value except a and b, all others are passed by reference;        

= , &a, &b : except for a and b reference transfer, others are value transfer

In parentheses:

 Identifies the parameters of the overloaded () operator, if there are no parameters, you can leave it blank

Parameters can be passed by value and by reference

Modifiable identifiers:

 mutable: Modify the value of the copy passed in by value instead of modifying the body. This part can be omitted

 Function return value:

 -> Return value type, which identifies the type of return value of the function, but when the return value is void, or when there is only one return in the function body (at this time, the compiler can automatically infer the return value type), this part can be omitted

 Function body:

{}, identifies the implementation of the function, this part cannot be omitted, but the function body can be empty 

 Use of lambda expressions:

When the third expression is this, it can be omitted

    //利用lambda表达式实现点击按钮关闭窗口
    QPushButton *btn2=new QPushButton("关闭",this);
    btn2->move(300,0);

    connect(btn2,&QPushButton::clicked,this,[=](){
        this->close();
        emit zt->hungry("烤腰子");
        btn2->setText("aaa");
    });

3.5 Open Close control implementation case

#include "widget.h"
#include<QPushButton>
#pragma execution_character_set("utf-8")//防止乱码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QWidget *New_Window = new QWidget;
    New_Window->setWindowTitle("点击open出现的");
    QPushButton *btn = new QPushButton("Open",this);
    btn->resize(100,50);
    btn->move(300,400);
    resize(800,800);
    setWindowTitle("黑马练习一");

    connect(btn,&QPushButton::clicked,New_Window,[=](){
        if(btn->text()=="Open")
        {
            New_Window->show();
            btn->setText("Close");
        }
        else
        {
            New_Window->close();
        }
    });
}

Widget::~Widget()
{
}

4.QMainWindow

 4.1 Menu bar:

QMenuBar *bar = menuBar();//创建菜单栏,菜单栏只能有一个

setMenuBar(bar);//将菜单栏放入到窗口中


QMenu * fileMenu=bar->addMenu("文件");    //创建菜单
QMenu * editMenu=bar->addMenu("编辑");    //返回的是QMenu *

   
fileMenu->addAction("新建");//创建菜单项目,返回的是QAction *
fileMenu->addSeparator();//添加分隔线
fileMenu->addAction("打开");

4.2 Toolbar:


    QToolBar *toolBar = new QToolBar(this);  //工具栏 ,可以有多个

    //将工具栏放在窗口中addToolBar
    addToolBar(Qt::LeftToolBarArea,toolBar);//参数一:自定义工具栏默认位置

    //后期设置  只允许 左右停靠
    toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);

    //设置浮动操作
    toolBar->setFloatable(0);//bool类型,0代表不允许浮动

    //设置移动(总开关)
    toolBar->setMovable(0);//bool型,0-不允许移动,1-允许


    toolBar->addAction("新建");    //工具栏中可以 设置内容
    toolBar->addSeparator();//分割线
    toolBar->addAction("打开");

    QPushButton *btn = new QPushButton("open",this);    
    toolBar->addWidget(btn);//工具栏中添加控件

 4.3 Status bar:

    QStatusBar *stBar= statusBar(); //状态栏  最多只能有一个

    setStatusBar(stBar);    //设置在窗口中

    QLabel *label = new QLabel("提示信息",this);    //放标签控件
    stBar->addWidget(label);//左侧

    QLabel *label2 = new QLabel("右侧提示信息",this);
    stBar->addPermanentWidget(label2);//右侧

4.4 Riveted parts (floating window):


    QDockWidget *dockwidget = new QDockWidget("浮动",this);//铆接部件(浮动窗口) 可以有多个
    addDockWidget(Qt::BottomDockWidgetArea,dockwidget);

    //设置后期停靠区域,只允许上下
    dockwidget->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);

4.5 Central part: 


    //设置中心部件  只能有一个
    QTextEdit * edit = new QTextEdit(this);
    setCentralWidget(edit);

4.6 All codes 

#include "mainwindow.h"
#pragma execution_character_set("utf-8")//防止乱码
#include<QMenuBar>
#include<qtoolbar.h>
#include<QDebug>
#include<QPushButton>
#include<QStatusBar>
#include<QLabel>
#include<QDockWidget>
#include<QTextEdit>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    resize(600,600);//重置窗口

    //创建菜单栏,菜单栏只能有一个
    QMenuBar *bar = menuBar();
    //将菜单栏放入到窗口中
    setMenuBar(bar);

    //创建菜单
    QMenu * fileMenu=bar->addMenu("文件");
    QMenu * editMenu=bar->addMenu("编辑");

    //创建菜单项目
    fileMenu->addAction("新建");
    //添加分隔线
    fileMenu->addSeparator();
    fileMenu->addAction("打开");


    //工具栏 ,可以有多个
    QToolBar *toolBar = new QToolBar(this);
    //将工具栏放在窗口中addToolBar
    addToolBar(Qt::LeftToolBarArea,toolBar);//自定义工具栏默认位置

    //后期设置  只允许 左右停靠
    toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);

    //设置浮动操作
    toolBar->setFloatable(0);//bool类型,0代表不允许浮动
    //设置移动(总开关)
    toolBar->setMovable(0);//bool型,0-不允许移动,1-允许

    //工具栏中可以 设置内容
    toolBar->addAction("新建");
    toolBar->addSeparator();//分割线
    toolBar->addAction("打开");
    //工具栏中添加控件
    QPushButton *btn = new QPushButton("open",this);
    toolBar->addWidget(btn);

    //状态栏  最多只能有一个
    QStatusBar *stBar= statusBar();
    //设置在窗口中
    setStatusBar(stBar);
    //放标签控件
    QLabel *label = new QLabel("提示信息",this);
    stBar->addWidget(label);//左侧
    QLabel *label2 = new QLabel("右侧提示信息",this);
    stBar->addPermanentWidget(label2);//右侧

    //铆接部件(浮动窗口) 可以有多个
    QDockWidget *dockwidget = new QDockWidget("浮动",this);
    addDockWidget(Qt::BottomDockWidgetArea,dockwidget);
    //设置后期停靠区域,只允许上下
    dockwidget->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);



    //设置中心部件  只能有一个
    QTextEdit * edit = new QTextEdit(this);
    setCentralWidget(edit);

}

MainWindow::~MainWindow()
{
}

4.7 Resource file addition

1. Copy the picture file to the project file

2. Create a new file, right click on the project -> add new file -> Qt -> Qt Resource File -> name it

3.起名res->生成res.qrc

4.res.qrc打开方式:右键->open  in editor

5.添加前缀->添加文件

6.使用”:+前缀名+文件名“

    //一般
    ui->actionnew->setIcon(QIcon("D:\\photo\\a.jpg"));

    //使用添加QT资源  ":+前缀名+文件名"
    ui->actionnew->setIcon(QIcon(":/new/prefix1/photo/a.jpg"));

5.对话框

对话框  分类:模态对话框(不可以对其他窗口进行操作)和 非模态对话框(可以对其他窗口进行操作)

5.1自定义消息框 

5.1.1模态创建: 

        //模态创建  有阻塞功能
        QDialog dlg(this);
        dlg.resize(200,100);
        dlg.exec();

 5.1.2非模态创建:


        //非模态对话框创建,防止一闪而过,所以创建在堆区
        QDialog  *dlg2=new QDialog(this);
        dlg2->resize(500,100);
        dlg2->setAttribute(Qt::WA_DeleteOnClose);//关闭小对话框时会释放堆区数据
        dlg2->show();

 5.2标准对话框

 标准对话框是Qt内置的一系列对话框。

Qt的内置对话框大致分为以下基类:

QClorDialog:        选择颜色

QFileDialog:        选择文件或者目录

QFontDialog:        选择字体

QInputDialog:        允许用户输入一个值,并将其值返回

QMessageBox:        模态对话框,用于显示信息,询问问题等

QPageSetupDialog:        为打印机提供纸张相关的选项

QPrintPreviewDialog:        打印预览

QProngressDialog:        显示操作过程

 5.2.1QMessageBox下的四种对话框:

        //错误对话框
        QMessageBox::critical(this,"错误提示","出错了404");

        //信息对话框
        QMessageBox::information(this,"提示","5+3=8");
//问题对话框question(父亲,标题,内容,按键类型,默认按键)
        if(QMessageBox::Save==QMessageBox::question(this,"问题对话框","who is who?",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
        {
                qDebug()<<"选择的是save";
        }
        else if(QMessageBox::Cancel==QMessageBox::question(this,"问题对话框","who is who?",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
        {
            qDebug()<<"选择的是Cancel";
        }
        //警告对话框
        QMessageBox::warning(this,"警告","你小子今晚别睡太死!");

5.3其他标准对话框

 5.3.1颜色对话框:


        //其他标准对话框
        QColor  color =QColorDialog::getColor(QColor(255,0,0));//返回值是QColor类型
        qDebug()<<color.red();

5.3.2文件对话框:


        //文件对话框QFileDialog::getOpenFileName(父亲,标题,默认打开路径,过滤文件格式)
        //返回值是选取的路径
        QString str = QFileDialog::getOpenFileName(this,"打开文件","E:\\Project\\QT_project\\HeiMa_Class\\HeiMa_SecondDay_03","(*.txt)");//返回值QString
        qDebug()<<str;

5.3.3字体对话框: 

        //选择字体对话框
        bool flag;
        QFont font = QFontDialog::getFont(&flag,QFont("仿宋",36));
        qDebug()<<font.

5.4全部代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#pragma execution_character_set("utf-8")//防止乱码
#include<QDialog>
#include<QDebug>
#include<QMessageBox>
#include<QColorDialog>
#include<QFileDialog>
#include<QFontDialog>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //点击新建按钮,弹出一个对话框
    connect(ui->actionnew,&QAction::triggered,[=](){
//        //对话框  分类:模态对话框(不可以对其他窗口进行操作)和 非模态对话框(可以对其他窗口进行操作)
//        //模态创建  有阻塞功能
//        QDialog dlg(this);
//        dlg.resize(200,100);
//        dlg.exec();


//        qDebug()<<"模态对话框弹出了";

//        //非模态对话框创建,防止一闪而过,所以创建在堆区
//        QDialog  *dlg2=new QDialog(this);
//        dlg2->resize(500,100);
//        dlg2->setAttribute(Qt::WA_DeleteOnClose);//关闭小对话框时会释放堆区数据
//        dlg2->show();



        //消息对话框
        //错误对话框
        //QMessageBox::critical(this,"错误提示","出错了404");
        //信息对话框
        //QMessageBox::information(this,"提示","5+3=8");
        //问题对话框question(父亲,标题,内容,按键类型,默认按键)
//        if(QMessageBox::Save==QMessageBox::question(this,"问题对话框","who is who?",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
//        {
//                qDebug()<<"选择的是save";
//        }
//        else if(QMessageBox::Cancel==QMessageBox::question(this,"问题对话框","who is who?",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
//        {
//            qDebug()<<"选择的是Cancel";
//        }
        //警告对话框
        //QMessageBox::warning(this,"警告","你小子今晚别睡太死!");

        //其他标准对话框
        //QColor  color =QColorDialog::getColor(QColor(255,0,0));//返回值是QColor类型
        //qDebug()<<color.red();

        //文件对话框QFileDialog::getOpenFileName(父亲,标题,默认打开路径,过滤文件格式)
        //返回值是选取的路径
        //QString str = QFileDialog::getOpenFileName(this,"打开文件","E:\\Project\\QT_project\\HeiMa_Class\\HeiMa_SecondDay_03","(*.txt)");//返回值QString
        //qDebug()<<str;

        //选择字体对话框
        bool flag;
        QFont font = QFontDialog::getFont(&flag,QFont("仿宋",36));
        qDebug()<<font;
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

6.界面布局

 ->实现登录窗口,利用布局方式对窗口进行美化

->选取widget进行布局,水平布局,垂直布局,栅格布局(几行几列的时候用)

->给用户名、密码、登录、退除按钮进行布局

->默认窗口和控件之间有9像素间隙,可以选中窗口,在layout中可以修改

->利用弹簧进行布局

 7.控件

 7.1按钮组

QPushButton  常用按钮

QToolButton 工具按钮,一般用于显示图片,如果想显示文字,修改风格toolbuttonStyle,突起风格:autoRaise

Radio Button  单选按钮,设置默认 setchecked(true)

checkbox  多选按钮,监听状态,2是选中,1是半选,0是未选

 7.2QListWidget 列表容器

    //利用listwidget写诗
    QListWidgetItem * item = new QListWidgetItem("锄禾日当午");
    //将这行诗放到listwidget中
    ui->listWidget->addItem(item);
    item->setTextAlignment(Qt::AlignHCenter);//设置水平剧中

    //第二种方法,没办法居中,但是可以一次多行
    //QStringList   QList<QString>
    QStringList  list;
    list <<"锄禾日当午"<<"汗滴禾下土"<<"谁知盘中餐"<<"粒粒皆辛苦";
    ui->listWidget->addItems(list);

 7.3QTreeWidget 树控件

 //treewidget树控件使用

    //设置水平头
    ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍");
 //设置力量
    QTreeWidgetItem *poweritem = new QTreeWidgetItem(QStringList()<<"力量");
    //加载顶层的节点
    ui->treeWidget->addTopLevelItem(poweritem);
    //设置敏捷
    QTreeWidgetItem *minjieitem = new QTreeWidgetItem(QStringList()<<"敏捷");
    //
    ui->treeWidget->addTopLevelItem(minjieitem);
    //设置速度
    QTreeWidgetItem *zhiliitem = new QTreeWidgetItem(QStringList()<<"智力");
    //
    ui->treeWidget->addTopLevelItem(zhiliitem);
    //追加子节点
    QStringList list;
    list<<"四大金刚i上看到你告诉官方";
    QTreeWidgetItem *l1 = new QTreeWidgetItem(list);
    poweritem->addChild(l1);

  7.4QTableWidget 表格控件

    //设置列数
    ui->tableWidget->setColumnCount(3);//3列

    //设置水平表头
    ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
    //设置行数
    ui->tableWidget->setRowCount(5);

 QList<QString>nameList; == QStringList nameList;

    //设置正文
    //第一种可以这样写
    //ui->tableWidget->setItem(0,0,new QTableWidgetItem("亚瑟"));//0行0列

    //也可以for循环
    QList<QString>nameList;
    nameList<<"亚瑟"<<"安其拉"<<"赵云"<<"张飞"<<"孙悟空";

    QList<QString>sexList;
    sexList<<"男"<<"女"<<"男"<<"男"<<"未知";

    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)));
        //int转QString
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
    }

7.5自定义封装控件

1.添加新文件->QT->设计师界面类

 2.在新建的.ui文件中设置QSpinBox和QSlider两个控件

 3.在widget.ui中使用自定义的控件

 拖拽widget控件,右键提升窗口成刚才设置的ui文件名

 4.联动效果

在新建的.cpp文件中设置信号槽联动 

  //QSpinBox移动  QSlider跟着移动
    void(QSpinBox::* spSignal)(int) = &QSpinBox::valueChanged;
    connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
//QSlider移动  QSpinBox跟着移动
    connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

5.提供接口,获取数字和设置数字

 在widget.ui中提供两个按钮

在新建的.h文件中添加声明

    void setNum(int num);//设置数字

    int getNum();//获取 数字

然后在新建的.cpp文件中构建函数体

void SmallWidge::setNum(int num)//设置 数字
{
    ui->spinBox->setValue(num);
}

int SmallWidge::getNum()//获得  数字
{
    return ui->spinBox->value();
}

然后在widget.cpp文件中添加信号槽的联动

 //点击获取  获取值
    connect(ui->btnGet,&QPushButton::clicked,[=](){
        qDebug()<<ui->widget->getNum();
    });
    //点击设置  设置到一半
    connect(ui->btnSet,&QPushButton::clicked,[=](){
        ui->widget->setNum(50);

8.QT中的鼠标事件

在widget.ui中设置一个label

Then create a new C++ class named mylabel (including .h, .cpp) 

Note: mylabel class should inherit QLabel

8.1 Mouse enter event enterEvent

 8.1.1 Add declaration in the mylabel.h header file

    //鼠标进入
    void enterEvent(QEvent *event);

8.1.2 Set the function body in the mylabel.cpp file

void myLabel::enterEvent(QEvent *event)
{
    //qDebug()<<"鼠标进入了";
}

8.2 Mouse leave event leaveEvent

8.2.1 Add declaration in mylabel.h

    //鼠标离开
    void leaveEvent(QEvent *event);

8.2.2 Set the function body in the mylabel.cpp file

void myLabel::leaveEvent(QEvent *event)
{
    //qDebug()<<"鼠标退出了";
}

8.3. Mouse down Mouse release Mouse move 

8.3.1 Declaration in mylabel.h

    virtual void mousePressEvent(QMouseEvent *ev);//鼠标按下

    virtual void mouseReleaseEvent(QMouseEvent *ev);//鼠标释放

    virtual void mouseMoveEvent(QMouseEvent *ev);//鼠标移动

8.3.2 ev->x() ev->y() x coordinate, y coordinate

QString("x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());

8.3.3 ev->button() judges the left and right buttons 

Left is Qt::LeftButton and right is Qt::RightButton 

void myLabel::mousePressEvent(QMouseEvent *ev)
{
    //鼠标左键按下  提示信息
    if(ev->button()==Qt::LeftButton)
    {
    }
}

8.3.4 ev->buttons() judge combination button   

Judging the left and right keys when moving, combining with operators

void myLabel::mouseMoveEvent(QMouseEvent *ev)
{
    if(ev->buttons()&Qt::LeftButton)//位与运算符 同真才为真
    {
    }
}

8.3.5 Setting Mouse Tracking 

    //设置鼠标追踪,鼠标放上去不需要点击即可打印
    setMouseTracking(true);

8.3.6 Write function body in mylabel.cpp

#include "mylabel.h"
#include<QDebug>
#include<QMouseEvent>
#pragma execution_character_set("utf-8")//防止乱码
myLabel::myLabel(QWidget *parent)
    : QLabel{parent}
{
    //设置鼠标追踪,鼠标放上去不需要点击即可打印
    setMouseTracking(true);
}

void myLabel::enterEvent(QEvent *event)
{
    qDebug()<<"鼠标进入了";
}

void myLabel::leaveEvent(QEvent *event)
{
    qDebug()<<"鼠标退出了";
}

void myLabel::mousePressEvent(QMouseEvent *ev)
{
    //鼠标左键按下  提示信息
    if(ev->button()==Qt::LeftButton)
    {
    QString str=QString("鼠标按下了,x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug()<<str;
    }
}

void myLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    if(ev->button()==Qt::LeftButton)
    {
    QString str=QString("鼠标释放了,x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug()<<str;
    }
}

void myLabel::mouseMoveEvent(QMouseEvent *ev)
{
    if(ev->buttons()&Qt::LeftButton)//位与运算符 同真才为真
    {
        QString str=QString("鼠标移动了,x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug()<<str;
    }
}

8.3.7 Format strings   

QString str=QString("鼠标按下了,x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;

9. Timer, distributor, filter, drawing

9.1 The first way of timer 

9.1.1 Using the event void timerEvent (QTimerEvent *ev)

Write in widget.h: 

    //重写定时器的事件
    void timerEvent(QTimerEvent *);

9.1.2 Start timer startTimer() millisecond unit

    //启动定时器
    id1=startTimer(1000);//参数1:间隔,单位是毫秒ms

9.1.3 The return value of timerEvent is the unique identifier of the timer

 The return value of timerEvent is the unique identifier of the timer, which can be compared with ev->timerId

 Write in widget.h:

    int id1;//定时器1的唯一标识
    int id2;//定时器2的唯一标识

Write in widget.cpp: 

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //启动定时器
    id1=startTimer(1000);//参数1:间隔,单位是毫秒ms

    id2=startTimer(2000);
}
void Widget::timerEvent(QTimerEvent *ev)
{
    if(ev->timerId()==id1)
    {static int num =1;
    //label_2每隔1秒+1
    ui->label_2->setText(QString::number(num++));}
     if(ev->timerId()==id2)
    {//label_3每隔2秒+1
    static int num2 =1;
    ui->label_3->setText(QString::number(num2++));}
}
Widget::~Widget()
{
    delete ui;
}

9.2 Second way of timer

9.2.1 Class QTimer using timers 

#include<QTimer>//定时器的类

 9.2.2 Creating Timer Objects

    QTimer *timer = new QTimer(this);//创建定时器对象

 9.2.3 Start timer timer->start

    //启动定时器
    timer->start(500);//0.5s

9.2.4 Signal-slot connections 

    connect(timer,&QTimer::timeout,[=](){
        static int num =1;//信号:timeout,进行监听
        ui->label_4->setText(QString::number(num++));
    });

9.2.5 Pause timer->stop

    //点击暂停按钮,实现停止定时器
    connect(ui->btn,&QPushButton::clicked,[=](){
        timer->stop();
    });

9.3 Event dispatcher event

 It is used for event distribution and can also be intercepted, but it is not recommended

9.3.1  bool event(QEvent * e)


    //通过event事件分发器 拦截 鼠标按下事件
    bool event(QEvent *e);

9.3.2  返回值若是true,则代表用户处理这个时间,不向下分发了

bool myLabel::event(QEvent *e)
{
    //如果是鼠标按下,事件分发器中做拦截操作
    if(e->type()==QEvent::MouseButtonPress)
    {
        QMouseEvent *ev=static_cast<QMouseEvent *>(e);//将e转换为ev
        QString str=QString("Event函数中,鼠标按下了,x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug()<<str;
        return true;//true代表用户自己处理事件,不向下分发
    }
    //其他事件  交给父类处理  默认处理
    return QLabel::event(e);
}

9.3.3   e->type() 可以判断事件

bool myLabel::event(QEvent *e)
{
    //如果是鼠标按下,事件分发器中做拦截操作
    if(e->type()==QEvent::MouseButtonPress)
    {}
}

9.4事件过滤器

 

 在程序将事件分发到事件分发器前,可以利用过滤器做拦截

9.4.1给控件安装事件过滤器

    //1.给label1安装事件过滤器
    ui->label->installEventFilter(this);

9.4.2重写eventFilter(obj,e)函数

    //重写事件过滤器的事件
    bool eventFilter(QObject *,QEvent *);
 //2.重写eventfilter事件
bool Widget::eventFilter(QObject *obj, QEvent *e)
{
    if(obj==ui->label)
    {
        if(e->type()==QEvent::MouseButtonPress)
        {
            QMouseEvent *ev=static_cast<QMouseEvent *>(e);//将e转换为ev
            QString str=QString("事件过滤器中,鼠标按下了,x=%1  y=%2  globalX=%3  globalY=%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
            qDebug()<<str;
            return true;//true代表用户自己处理事件,不向下分发
        }
    }
    //其他事件  交给父类处理  默认处理
    return QWidget::eventFilter(obj,e);
}

9.5 QPainter绘图

 9.5.1绘图事件  void paintEvent

    //绘图事件
    void paintEvent(QPaintEvent *);

9.5.2声明一个画家对象

    //实例化画家对象  this指定的是绘图的设备
    QPainter painter(this);

 9.5.3画图、画文字、设置风格等

void Widget::paintEvent(QPaintEvent *)
{
    //实例化画家对象  this指定的是绘图的设备
    QPainter painter(this);

    //设置画笔
    QPen pen(QColor(255,0,0));
    //设置画笔宽度
    pen.setWidth(3);
    //设置画笔风格
    pen.setStyle(Qt::DotLine);
    //使用画笔
    painter.setPen(pen);
    //设置画刷
    QBrush brush(Qt::cyan);
    //设置画刷风格
    brush.setStyle(Qt::Dense7Pattern);
    //使用画刷
    painter.setBrush(brush);
    //划线
    painter.drawLine(QPoint(0,0),QPoint(100,100));
    //画圆
    painter.drawEllipse(QPoint(100,100),50,50);
    //❀矩形
    painter.drawRect(QRect(200,200,200,50));
    //画文字
    painter.drawText(QRect(50,200,150,50),"好好学习,天天向上");

}

9.6  QPainter 高级设置

9.6.1抗锯齿操作  (效率较低)

    painter.drawEllipse(QPoint(100,50),50,50);
    //设置抗锯齿能力  效率较低
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawEllipse(QPoint(200,50),50,50);

9.6.2对画家进行移动

painter.translate(100,0);

 9.6.3保存画家状态

painter.save();

9.6.4还原状态

painter.restore();

高级设置: 

    //高级设置///
    QPainter painter(this);
    painter.drawEllipse(QPoint(100,50),50,50);
    //设置抗锯齿能力  效率较低
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawEllipse(QPoint(200,50),50,50);

    //画矩形
    painter.drawRect(QRect(20,20,50,50));
    //让画家移动位置
    painter.translate(100,0);
    //保存画家状态
    painter.save();
    painter.drawRect(QRect(20,20,50,50));

    painter.translate(100,0);
    //还原画家保存状态
    painter.restore();
    painter.drawRect(QRect(20,20,50,50));

9.7手动调用绘图事件

9.7.1利用画家画图片

painter.drawPixmap(posX,0,QPixmap(":/xinglixiang1.jpg"));

 9.7.2利用update手动调用绘图事件

    //点击移动按钮  移动图片
    connect(ui->pushButton,&QPushButton::clicked,[=](){
    //如果手动调用绘图事件  用update更新
        posX+=20;
        update();
    /利用画家  画资源图片///
    QPainter painter(this);
    //如果超出屏幕 从0开始
    if(posX>this->width())
    {
        posX = 0;
    }
    painter.drawPixmap(posX,0,QPixmap(":/xinglixiang1.jpg"));

9.8 QPaintDevice绘图设备

 QPixmap,QBitmap(黑白色),QPicture,QWidget;QImage

9.8.1QPixmap

    /pixmap绘图设备  专门为平台做了显示的优化///
    QPixmap pix(500,500);

    //填充颜色
    pix.fill(Qt::red);
    //声明画家
    QPainter painter(&pix);
    painter.setPen(QPen(Qt::green));
    painter.drawEllipse(QPoint(250,250),100,100);

    //保存
    pix.save("E:\\pix.png");

9.8.2QImage

    //QImage  绘图设备   可以对像素进行访问///
    QImage img(500,500,QImage::Format_RGB32);
    img.fill(Qt::blue);
    QPainter painter(&img);
    painter.setPen(QPen(Qt::red));
    painter.drawEllipse(QPoint(250,250),100,100);
    //保存
    img.save("E:\\img.png");

 可以对像素进行访问

    //绘图事件
    void paintEvent(QPaintEvent *);
void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //利用QImage对像素进行修改
    QImage img;
    img.load(":/color.jpg");

    //修改像素点
    for(int i=50;i<100;i++)
    {
        for(int j=50;j<100;j++)
        {
            QRgb value = qRgb(255,0,0);
            img.setPixel(i,j,value);
        }
    }

    painter.drawImage(0,0,img);
}

9.8.3QPicture

    ///QPicture 绘图设备   可以记录和重现绘图指令///
    QPicture pic;
    QPainter painter;
    painter.begin(&pic);//开始往pic画

    painter.setPen(QPen(Qt::cyan));
    painter.drawEllipse(QPoint(250,250),100,100);

    painter.end();//结束画画
    //保存
    pic.save("E:\\pic.syh");

 可以记录和重现绘图指令

    //重现QPicture的绘图指令
    QPainter painter(this);
    QPicture pic;
    pic.load("E:\\pic.syh");
    painter.drawPicture(0,0,pic);

10 QFile 对文件进行读写操作

 设置一个ui界面如下

 准备一个txt文档

 10.1读文件

 10.1.1信号槽连接按钮与文件

 //点击选取文件按钮,弹出文件对话框
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","E:\\杂七杂八\\长恨歌.txt");

以下代码均在信号槽连接中: 

10.1.2将路径放在lineEdit中 

        //将路径放在lineEdit中
        ui->lineEdit->setText(path);

10.1.3读取的文件格式

QFile默认支持的格式是utf-8
        //编码格式类
        QTextCodec *codec = QTextCodec::codecForName("gbk");

10.1.4只读方式打开文件

        QFile file(path);//参数就是读取文件的路径
        //设置打开方式
        file.open(QIODevice::ReadOnly);//只读

10.1.5读取文件

全部读取 

QByteArray array = file.readAll();

一行一行读取 

        QByteArray array;
        while(!file.atEnd())//文件尾的条件
        {array += file.readLine();//按行读
        };

10.1.6文件尾部

file.atEnd()

10.1.7读到的数据放入文本框

         //将读到的数据放入textEdit
        ui->textEdit->setText(array);

10.1.8需要转格式读取

        //转格式
        ui->textEdit->setText(codec->toUnicode(array));
        file.open(QIODevice::Append);//用追加的方式进行写
        file.write("十多年佛山呢过分啊");
        file.close();

10.1.9对文件进行关闭

        file.close();

10.2写文件

        file.open(QIODevice::Append);//用追加的方式进行写
        file.write("十多年佛山呢过分啊");
        file.close();

10.3读写文件全部代码

#include "widget.h"
#include "ui_widget.h"
#pragma execution_character_set("utf-8")//防止乱码
#include<QFileDialog>
#include<QFile>
#include<QTextCodec>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //点击选取文件按钮,弹出文件对话框
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","E:\\杂七杂八\\长恨歌.txt");
        //将路径放在lineEdit中
        ui->lineEdit->setText(path);

        //编码格式类
        //QTextCodec *codec = QTextCodec::codecForName("gbk");
        //读取内容放到textEdit中
        //QFile默认支持的格式是utf-8
        QFile file(path);//参数就是读取文件的路径
        //设置打开方式
        file.open(QIODevice::ReadOnly);//只读

        //QByteArray array = file.readAll();

        QByteArray array;
        while(!file.atEnd())//文件尾的条件
        {array += file.readLine();//按行读
        };


        //将读到的数据放入textEdit
        ui->textEdit->setText(array);
        //转格式
        //ui->textEdit->setText(codec->toUnicode(array));

        //对文件对象进行关闭
        file.close();




        //进行写文件
        file.open(QIODevice::Append);//用追加的方式进行写
        file.write("十多年佛山呢过分啊");
        file.close();
    });
}

Widget::~Widget()
{
    delete ui;
}

 10.4 QFlieInfo读取文件信息

        QFileInfo info(path);
        qDebug()<<"文件的大小:"<<info.size();
        qDebug()<<"文件的后缀名:"<<info.suffix();
        qDebug()<<"文件的名称:"<<info.fileName();
        qDebug()<<"文件的路径:"<<info.filePath();
        qDebug()<<"文件的创建日期:"<<info.created().toString("yyyy/MM/dd hh:mm:ss");
        qDebug()<<"文件的最后修改日期:"<<info.lastModified().toString("yyyy/MM/dd hh:mm:ss");

11翻金币的案例

Gold coin resources:  https://pan.baidu.com/s/1EV-Wph01AKy69C3Orwqw2g#list/path=%2F

11.1 Create a project and add resource configuration

        Create a project and add the required resources to the file

11.2 Project Configuration Settings Background Size Title Background Icon 

11.2.1 Configure size, icon, title, exit button

    //配置主场景

    //设置固定大小
    setFixedSize(320,588);

    //设置图标
    setWindowIcon(QIcon(":/res/Coin0001.png"));

    //设置标题
    setWindowTitle("翻金币主场景");

    //退出按钮的实现
    connect(ui->actionquit,&QAction::triggered,[=](){
        this->close();
    });

11.2.2 Configuration background 

    //重写paintEvent事件  画背景图
    void paintEvent(QPaintEvent *);
//重写paintEvent事件 画背景图
void MainScene::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/PlayLevelSceneBg.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);//背景拉伸满屏

    //画背景上的图标
    pix.load(":/res/Title.png");
    pix = pix.scaled(pix.width()*0.5,pix.height()*0.5);//缩放图标
    painter.drawPixmap(10,30,pix);
}

11.3 Creating the start button

       11.3.1 Encapsulating a custom button MyPushButton

                 Create a new class as MyPushButton

                Main scene creation start button 

   //开始的按钮
    MyPushButton * startBtn = new  MyPushButton(":/res/MenuSceneStartButton.png");
    startBtn->setParent(this);
    startBtn->move(this->width()*0.5-startBtn->width()*0.5,this->height()*0.7);

        11.3.2 Constructor (the picture is displayed by default, and the picture is displayed after pressing)

  //构造函数 参数1,正常显示的图片路径  参数2,按下后显示的图片路径
    MyPushButton(QString normalImg,QString perssImg="");

    //成员属性  保存用户传入的默认显示路径 以及按下后显示的图片路径
    QString normalImgPath;
    QString pressImgPath;
MyPushButton::MyPushButton(QString normalImg, QString perssImg)
{
    this->normalImgPath=normalImg;
    this->pressImgPath =pressImgPath;

    QPixmap pix;
    bool  ret =pix.load(normalImg);
    if(!ret)
    {
        qDebug()<<"图片加载失败";
        return;
    }

    //设置图片的固定大小
    this->setFixedSize(pix.width(),pix.height());

    //设置不规则图片样式
    this->setStyleSheet("QPushButton{border:0px}");

    //设置图标
    this->setIcon(pix);

    //设置图标大小
    this->setIconSize(QSize(pix.width(),pix.height()));

}

        11.3.3 Start making special effects zoom1, zoom2

    //弹跳特效
    void zoom1();//向下跳
    void zoom2();//向上跳
void MyPushButton::zoom1()
{
    //创建一个动画对象
    QPropertyAnimation * animation = new QPropertyAnimation(this,"geometry");
    //设置动画时间间隔
    animation->setDuration(200);
    //起始位置
    animation->setStartValue(QRect(this->x(),this->y(),this->width(),this->height()));
    //结束位置
    animation->setEndValue(QRect(this->x(),this->y()+10,this->width(),this->height()));
    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);
    //开始执行动画
    animation->start();
}

void MyPushButton::zoom2()
{
    //创建一个动画对象
    QPropertyAnimation * animation = new QPropertyAnimation(this,"geometry");
    //设置动画时间间隔
    animation->setDuration(200);
    //起始位置
    animation->setStartValue(QRect(this->x(),this->y()+10,this->width(),this->height()));
    //结束位置
    animation->setEndValue(QRect(this->x(),this->y(),this->width(),this->height()));
    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);
    //开始执行动画
    animation->start();

}

11.4 Create a selection level scene

 Create a selection level scene class

        11.4.1 After clicking the start button, enter the selected level scene with a delay

                Main scene added: 

    ClooseLevelScene * chooseScene = NULL;
    connect(startBtn,&MyPushButton::clicked,[=](){
        qDebug()<<"点击了开始";
        //做一个弹起的特效
        startBtn->zoom1();
        //做一个回弹特效
        startBtn->zoom2();

        //延时进入到选择关卡场景
        QTimer::singleShot(200,this,[=](){
            //进入到选择关卡场景中
            //将自身隐藏
            this->hide();
            //显示选择关卡场景
            chooseScene->show();
        });
    });

       11.4.2 Configure the selected level scene (set the background size and title background icon) 

                Configure the relevant settings of the selected level scene 

  //配置选择关卡场景

    this->setFixedSize(320,588);

    //设置图标
    this->setWindowIcon(QPixmap(":/res/Coin0001.png"));

    //设置标题
    this->setWindowTitle("选择关卡");

    //创建菜单栏
    QMenuBar *bar = menuBar();
    setMenuBar(bar);

    //创建开始菜单
    QMenu * startMenu = bar->addMenu("开始");

    //创建退出的菜单项
    QAction * quitAction = startMenu->addAction("退出");

    //点击退出实现退出游戏
    connect(quitAction,&QAction::triggered,[=](){
        this->close();
    });

Configure the background image: 

    //重写paintEvent事件  画背景图
    void paintEvent(QPaintEvent *);
//重写paintEvent事件 画背景图
void ClooseLevelScene::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/OtherSceneBg.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);//背景拉伸满屏

    //画背景上的图标
    pix.load(":/res/Title.png");
    pix = pix.scaled(pix.width(),pix.height());//缩放图标
    painter.drawPixmap(40,30,pix);
}

        11.4.3 Creating the back button

    //返回按钮
    MyPushButton * backBtn = new MyPushButton(":/res/BackButton.png",":/res/BackButtonSelected.png");
    backBtn->setParent(this);
    backBtn->move(this->width()-backBtn->width(),this->height()-backBtn->height());

    //点击返回
    connect(backBtn,&MyPushButton::clicked,[=](){
        qDebug()<<"点击了返回按钮";
    });

         11.4.4 Return button special effect switching of the return level

    //重写按钮 按下  释放 事件
    void mousePressEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
    if(this->pressImgPath!="")//传入摁下图片非空,说明需要有按下状态,切图
    {
        QPixmap pix;
        bool  ret =pix.load(this->pressImgPath);
        if(!ret)
        {
            qDebug()<<"图片加载失败";
            return;
        }

        //设置图片的固定大小
        this->setFixedSize(pix.width(),pix.height());

        //设置不规则图片样式
        this->setStyleSheet("QPushButton{border:0px}");

        //设置图标
        this->setIcon(pix);

        //设置图标大小
        this->setIconSize(QSize(pix.width(),pix.height()));

    }
    //让父类执行其他的内容
    return QPushButton::mousePressEvent(e);
}

void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
    if(this->normalImgPath!="")//传入摁下图片非空,说明需要有按下状态,切为初始图片
    {
        QPixmap pix;
        bool  ret =pix.load(this->normalImgPath);
        if(!ret)
        {
            qDebug()<<"图片加载失败";
            return;
        }

        //设置图片的固定大小
        this->setFixedSize(pix.width(),pix.height());

        //设置不规则图片样式
        this->setStyleSheet("QPushButton{border:0px}");

        //设置图标
        this->setIcon(pix);

        //设置图标大小
        this->setIconSize(QSize(pix.width(),pix.height()));
    }
    //让父类执行其他内容
    return QPushButton::mouseReleaseEvent(e);
}

11.4.5 Switching between the start scene and the selected level scene

signals:
    //写一个自定义的信号,告诉主场景,点击了返回
    void chooseSceneBack();
    //点击返回
    connect(backBtn,&MyPushButton::clicked,[=](){
        //qDebug()<<"点击了返回按钮";
        //告诉主场景  我返回了  主场景监听ChooseLevelScene的返回按钮

        //做一个延时的返回
        QTimer::singleShot(200,this,[=](){
            emit this->chooseSceneBack();
        });
    //监听选择关卡的返回按钮的信号
    connect(chooseScene,&ClooseLevelScene::chooseSceneBack,this,[=](){
        chooseScene->hide();
        this->show();//重新显示主场景

11.5 Select level button creation

11.5.1 Creating a matrix with a single for loop 

 //创建选择关卡的按钮
    for(int i=0;i<20;i++)//单个for循环写矩阵
    {
        MyPushButton * menuBtn = new MyPushButton(":/res/LevelIcon.png");
        menuBtn->setParent(this);
        menuBtn->move(25+i%4 * 70,130+i/4 * 70);

        //监听每个按钮的点击事件
        connect(menuBtn,&MyPushButton::clicked,[=](){
            QString str = QString("您选择的是第 %1 关").arg(i+1);
            qDebug()<<str;
        });   

 11.5.2 Set the number of levels displayed on the button


        QLabel * label = new QLabel;
        label->setParent(this);
        label->setFixedSize(menuBtn->width(),menuBtn->height());
        label->setText(QString::number(i+1));
        label->move(25+i%4 * 70,130+i/4 * 70);

        //设置label上的文字对齐方式
        label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);//设置水平居中和垂直居中
        //设置让鼠标进行穿透(51号属性)
        label->setAttribute(Qt::WA_TransparentForMouseEvents);
    }

11.6 Basic configuration of gold coin flipping scene

Create a new class PlayScene, pay attention to select QmainWindow

11.6.1 Configure the game scene (set the background size title background icon) 

same as before 

11.6.2 Implement the back button to return to the previous scene 

same as before 

11.6.3 Realize the label of the display level

    //显示当前关卡数
    QLabel *label = new QLabel;
    label->setParent(this);
    QFont font;
    font.setFamily("仿宋");
    font.setPointSize(20);
    QString str1 = QString("Level:%1").arg(this->levelIndex);
    //将字体设置到标签控件中
    label->setFont(font);
    label->setText(str1);
    label->setGeometry(30,this->height()-50,120,50);

 11.7 Create a gold coin class

 11.7.1 First put the background pattern of gold coins into PlayScene


    //显示金币的背景图案
    for(int i = 0; i < 4 ; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            //绘制背景图片
            QLabel*label = new QLabel;
            label->setGeometry(0,0,50,50);
            label->setPixmap(QPixmap(":/res/BoardNode.png"));
            label->setParent(this);
            label->move(57+i*50,200+j*50);
        }
    }

11.7.2 Create MyCoin custom gold coin button class

    //参数代表传入的金币路径 还是银币路径
    MyCoin(QString btnImg);
MyCoin::MyCoin(QString btnImg)
{
    QPixmap pix;
    bool ret =pix.load(btnImg);
    if(!ret)
    {
        QString str = QString("图片 %1 加载失败").arg(btnImg);
        qDebug()<<str;
    }

    this->setFixedSize(pix.width(),pix.height());
    this->setStyleSheet("QPushButton{border:0px;}");
    this->setIcon(pix);
    this->setIconSize(QSize(pix.width(),pix.height()));
}

In the constructor, the gold coin that passes in the picture displayed by default

11.7.3 Create all gold coin buttons in playscene

    //显示金币的背景图案
    for(int i = 0; i < 4 ; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            //绘制背景图片
            QLabel*label = new QLabel;
            label->setGeometry(0,0,50,50);
            label->setPixmap(QPixmap(":/res/BoardNode.png"));
            label->setParent(this);
            label->move(57+i*50,200+j*50);

            //创建金币
            MyCoin * coin = new MyCoin(":/res/Coin0001.png");
            coin->setParent(this);
            coin->move(59+i*50,204+j*50);
        }
    }

11.8 The default display of each level

Introduce dataConfig.h and dataConfig.cpp files into the project

Write an array of int gameArray[4][4] in PlayScene to maintain the gold coin status of each level

Initialize the display of each level

11.9 Flip gold coin effects

 11.9.1 Add attribute posx posy bool flag to each coin

    //金币的属性
    int posX;//X坐标位置
    int posY;//Y坐标位置
    bool flag;//正反标识
  //给金币的属性赋值
            coin->posX=i;
            coin->posY=j;
            coin->flag=this->gameARRAY[i][j];//1正面 0反面

11.9.2 Add function to MyCoin

    //改变标志的方法
    void changeFlag();
    QTimer *timer1;//正面翻反面定时器
    QTimer *timer2;//反面翻正面定时器
    int min = 1;
    int max = 8;

    //执行动画的标志
    bool isAnimation = false;
    //初始化定时器对象
    timer1 = new QTimer(this);
    timer2 = new QTimer(this);
void MyCoin::changeFlag()
{
    //如果是正面翻转反面
    if(this->flag)
    {
        //开始正面翻反面的定时器
        timer1->start(30);
        isAnimation = true;//开始做动画
        this->flag =false;
    }
    else//相反
    {
        timer2->start(30);
        isAnimation = true;//开始做动画
        this->flag = true;
    }
}

11.9.3 Listening to Signals and Flipping



    //监听正面翻反面的信号  并且翻转
    connect(timer1,&QTimer::timeout,[=](){
        QPixmap pix;
        QString str = QString(":/res/Coin000%1.png").arg(this->min++);
        pix.load(str);

        this->setFixedSize(pix.width(),pix.height());
        this->setStyleSheet("QPushButton{border:0px;}");
        this->setIcon(pix);
        this->setIconSize(QSize(pix.width(),pix.height()));
        //判断  如果翻完了,将min重置为1
        if(this->min>this->max)
        {
            this->min = 1;
            isAnimation = false;
            timer1->stop();
        }
    });
     //监听反面翻正面的信号  并且翻转
    connect(timer2,&QTimer::timeout,[=](){
        QPixmap pix;
        QString str = QString(":/res/Coin000%1.png").arg(this->max--);
        pix.load(str);

        this->setFixedSize(pix.width(),pix.height());
        this->setStyleSheet("QPushButton{border:0px;}");
        this->setIcon(pix);
        this->setIconSize(QSize(pix.width(),pix.height()));
        //判断  如果翻完了,将min重置为1
        if(this->min>this->max)
        {
            this->max = 8;
            isAnimation = false;
            timer2->stop();
        }
    });

 //点击金币  进行翻转
            connect(coin,&MyCoin::clicked,[=](){
                coin->changeFlag();
                this->gameARRAY[i][j] = this->gameARRAY[i][j]==0?1:0;
            });

11.9.4 Solve the problem that the fast click effect is not good



    //重写 按下 和  释放
    void mousePressEvent(QMouseEvent *e);
void MyCoin::mousePressEvent(QMouseEvent *e)
{
    if(this->isAnimation==true)
    {
        return;
    }
    else
    {
        QPushButton::mousePressEvent(e);
    }
}

11.9.5 Click around the coin to flip it together

    MyCoin *coinBtn[4][4];
            
            //将金币放入到 金币的二维数组中 以便以后的维护
            coinBtn[i][j]=coin;
            //点击金币  进行翻转
            connect(coin,&MyCoin::clicked,[=](){
                coin->changeFlag();
                this->gameARRAY[i][j] = this->gameARRAY[i][j]==0?1:0;

                //翻转周围硬币
                QTimer::singleShot(300,this,[=](){
                    if(coin->posX+1<=3)//翻右侧金币
                    {
                        coinBtn[coin->posX+1][coin->posY]->changeFlag();
                        this->gameARRAY[coin->posX+1][coin->posY] = this->gameARRAY[coin->posX+1][coin->posY]==0?1:0;
                    }
                    //周围的左侧硬币翻转条件
                    if(coin->posX-1>=0)
                    {
                        coinBtn[coin->posX-1][coin->posY]->changeFlag();
                        this->gameARRAY[coin->posX-1][coin->posY] = this->gameARRAY[coin->posX-1][coin->posY]==0?1:0;
                    }
                    //上侧硬币翻转条件
                    if(coin->posY-1>=0)
                    {
                        coinBtn[coin->posX][coin->posY-1]->changeFlag();
                        this->gameARRAY[coin->posX][coin->posY-1] = this->gameARRAY[coin->posX][coin->posY-1]==0?1:0;
                    }
                    //下侧硬币翻转条件
                    if(coin->posY+1<=3)
                    {
                        coinBtn[coin->posX][coin->posY+1]->changeFlag();
                        this->gameARRAY[coin->posX][coin->posY+1] = this->gameARRAY[coin->posX][coin->posY+1]==0?1:0;
                    }
                });
            });

11.9.6 Determining Victory

Add the iswin flag to playsence to judge whether it is a victory 

    //是否胜利的标志
    bool isWin;
  //判断是否胜利
                    this->isWin = true;
                    for(int i = 0 ; i < 4 ; i++)
                    {
                        for(int j = 0 ; j < 4 ; j++)
                        {
                            if(coinBtn[i][j]->flag==false)//只要有一个是反面
                            {
                                this->isWin = false;
                                break;
                            }
                        }
                    }
                    if(this->isWin == true)
                    {
                        //胜利了
                        qDebug()<<"游戏胜利";
                        //将所有按钮的胜利标志改为true,再次点击,直接return
                        for(int i = 0 ; i < 4 ; i++)
                        {
                            for(int j = 0 ; j < 4 ; j++)
                            {
                                coinBtn[i][j]->isWin=true;
                            }
                        }
                    }

Add the judgment of iswin, if all are true, return directly 

void MyCoin::mousePressEvent(QMouseEvent *e)
{
    if(this->isAnimation||this->isWin==true)
    {
        return;
    }
    else
    {
        QPushButton::mousePressEvent(e);
    }
}

11.9.7 Victory Picture Settings

    //胜利图片的显示
    QLabel* winLable = new QLabel;
    QPixmap tmpPix;
    tmpPix.load(":/res/LevelCompletedDialogBg.png");
    winLable->setGeometry(0,0,tmpPix.width(),tmpPix.height());
    winLable->setPixmap(tmpPix);
    winLable->setParent(this);
    winLable->move((this->width()-tmpPix.width())*0.5,-tmpPix.height());
 if(this->isWin == true)
                    {
                        //胜利了
                        qDebug()<<"游戏胜利";
                        //将所有按钮的胜利标志改为true,再次点击,直接return
                        for(int i = 0 ; i < 4 ; i++)
                        {
                            for(int j = 0 ; j < 4 ; j++)
                            {
                                coinBtn[i][j]->isWin=true;
                            }
                        }
                        //将胜利的图片砸下来
                        QPropertyAnimation * animation = new QPropertyAnimation(winLable,"geometry");
                        //设置时间间隔
                        animation->setDuration(1000);
                        //设置开始位置
                        animation->setStartValue(QRect(winLable->x(),winLable->y(),winLable->width(),winLable->height()));
                        //设置结束位置
                        animation->setEndValue(QRect(winLable->x(),winLable->y()+114,winLable->width(),winLable->height()));
                        //设置缓和曲线
                        animation->setEasingCurve(QEasingCurve::OutBounce);
                        //执行动画
                        animation->start();
                    }

11.9.8 Sound Effect Settings

 The module multimedia to which QSound belongs needs to be loaded in the .pro file

    QSound *startSound = new QSound(":/res/TapButtonSound.wav",this);


    startSound->setLoops(-1);//设置循环,-1为无限循环
    startSound->play();

11.9.9 Keeping a position per scene

 Start going to the next scene:

            //设置choosescene场景的位置
            chooseScene->setGeometry(this->geometry());

 Return to the previous scene, written before show

        this->setGeometry(chooseScene->geometry());

 11.10 Project packaging and game expansion

 debug to release and run

Find the .exe, put it in the folder, and open the command prompt in this location

Find windeployqt in the bin in QT

Enter windeployqt file name.exe on the command line to run

Guess you like

Origin blog.csdn.net/weixin_58176527/article/details/127492141