QT入门到实战学习笔记

article/2025/10/25 3:49:11

学习笔记 

最新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利用画家画图片

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

9.8 QPaintDevice绘图设备

9.8.1QPixmap

9.8.2QImage

9.8.3QPicture

10 QFile 对文件进行读写操作

 10.1读文件

 10.1.1信号槽连接按钮与文件

10.1.2将路径放在lineEdit中 

10.1.3读取的文件格式

10.1.4只读方式打开文件

10.1.5读取文件

10.1.6文件尾部

10.1.7读到的数据放入文本框

10.1.8需要转格式读取

10.1.9对文件进行关闭

10.2写文件

10.3读写文件全部代码

 10.4 QFlieInfo读取文件信息

11翻金币的案例

11.1创建项目  添加资源配置

11.2项目配置设置背景 大小 标题 背景 图标 

11.2.1配置大小、图标、标题、退出按钮

11.2.2配置背景 

11.3创建开始按钮

       11.3.1 封装自定义的按钮 MyPushButton

        11.3.2构造函数(默认显示图片,按下后显示图片)

        11.3.3开始制作特效zoom1,zoom2

11.4创建选择关卡场景

        11.4.1点击开始按钮后延时进入到选择关卡场景

       11.4.2 配置选择关卡场景(设置背景 大小 标题 背景 图标) 

        11.4.3创建返回按钮

         11.4.4返回关卡的返回按钮特效切换

11.4.5 开始场景与选择关卡场景的切换

11.5选择关卡按钮创建

11.5.1单个for循环创建矩阵 

 11.5.2按钮上设置显示关卡数

11.6翻金币场景的基本配置

11.6.1配置游戏场景(设置背景 大小 标题 背景 图标) 

11.6.2实现返回按钮可以返回上一场景 

11.6.3实现显示关卡的label

 11.7创建金币类

 11.7.1先将金币的背景图案放入PlayScene中

11.7.2创建MyCoin自定义金币按钮类

11.7.3在playscene创建所有的金币按钮

11.8每个关卡的默认显示

11.9翻金币特效

 11.9.1给每个硬币加属性  posx  posy  bool flag

11.9.2给MyCoin加函数

11.9.3监听信号并翻转

11.9.4解决快速点击效果不好的问题

11.9.5点击硬币周围一起翻转

11.9.6判断胜利

11.9.7胜利图片设置

11.9.8音效设置

11.9.9每个场景保持一个位置

 11.10项目打包及游戏扩展


 1.创建一个QT文件

  •  点击创建项目,选择项目路径以及名称(不能含中文)
  •  默认创建有窗口类,基类有三种选择:Qwidget,QmyWindow,QDialog.main.cpp介绍
  • main函数:看注释
#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命名规范

类名:首字母大写,单词和单词之间首字母大写

函数名 变量名称:首字母小写,单词和单词之间首字母大写

1.2快捷键 

注释 :ctrl + /

运行: ctrl + r

编译: ctrl + b

字体缩放: ctrl + 鼠标滚轮

查找: ctrl + f

整行移动: ctrl + shift + ↑或↓

帮助文档:F1        

自动对齐:ctrl + i

同名之间的.h和.cpp切换:f4

2QPushButton创建

 创建QPushButtn *btn = new QPushButton

设置父亲  setParent(this)

设置文本   setText("文字")

设置位置   move(宽,高)

重新指定窗口大小  resize

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

设置固定窗口大小   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防止汉语乱码 

哪个文件需要,就在哪个上面加这行代码 

#pragma execution_character_set("utf-8")//防止乱码

 打开选项->文本编辑器->行为,如图设置

 打开编辑->select enconding如图设置

 

2.2对象树

 当创建的对象再堆区的时候,如果指定的父亲是Qobject派生下来的类或者Qobject子类派生下来的类,可以不用管理释放的操作,会将对象放入到对象树中

一定程度上简化了内存回收机制

 2.3Qt窗口坐标体系

 以左上角为远点(0,0),X向右增加,Y向下增加

 3信号和槽机制

connect(发送者,信号(函数地址),接收者,槽函数)

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

 3.1自定义信号和槽

自定义老师->饿了->学生->请客吃饭(饿了是信号,吃饭是槽)

创建老师和学生的类(Teacher;Student)->头文件声明->源文件槽函数实现

创建类:右键项目->添加新文件->class name(Teacher)->base class(一般为QObject)

头文件声明时:

 3.1.1自定义信号:

        自定义信号,写到signals下,老师饿了,所以写到teacher.h的signals下
        返回值是void,只需要声明,不需要实现
        可以有参数,可以重载

signals:void hungry();

3.1.2自定义槽:

        早期版本qt,必须写到public slots,高级版本可以下到public或者全局函数下

        学生请客,所以写到student.h的public下或public slots下

        返回值是void,需要声明,也需要实现

        可以有参数,可以发生重载

public slot:void treat();

 >源文件的槽函数实现: 

在student.cpp中实现 

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

 

 在创建老师和学生对象前,需要在Widget.h文件中先声明这两个对象,私有公共都可以

Teacher*zt;

student*st;

classIsOver也需要在Widget.h中声明   ,在cpp文件中实现

void classIsOver()

 Widget.cpp文件:

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();//触发的关键字:emitemit zt->hungry("烤腰子");
}

 触发信号的关键字:emit 

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

 3.2.1重载:

teacher.h文件中:

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

 student.h文件中:

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

 槽函数(学生请客吃饭)实现:

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

 3.2.2连接解决办法:

 需要利用函数指针,明确指向函数的地址

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

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

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

 

解决方法: 

QString->char* 先转成QByerArray(.toUtf8())再转char*()
qDebug()<<"请老师吃饭,老师要吃:"<<foodName.toUtf8().data();

3.3信号槽的拓展

 设置一下:点击一个按钮,触发下课信号

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

3.3.1无参信号和槽连接

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

3.3.2信号连接信号

(按钮->老师饿了->学生请客)

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

3.3.3断开信号:disconnect

disconnect(zt,teacherSignal2,st,studentSlot2);

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

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

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

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

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

3.4Lambda表达式 

[](){};

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

 []时Lambda的开始,必须存在,不能省略

中括号内:

=:值传递;        &:引用传递;        this:类似于=;        a:将a按值进行传递;

&a:将a按引用进行传递;                & ,a , b :除a,b值传递,其他都是引用传递;        

= ,&a ,&b:除a,b引用传递,其他都是值传递

小括号内:

 标识重载的()操作符的参数,没有参数时可以不写

参数可以通过按值和按引用两种方式进行传递

可修改标识符:

 mutable:修改按值传递进来的拷贝的值,而非修改本体。这部分可以省略

 函数返回值:

 ->返回值类型,标识函数返回值的类型,但返回值为void时,或者函数体中只有一处return的地方(此时编译器可以自动推断除返回值类型)时,这部分可以省略

 函数体:

{},标识函数的实现,这部分不能省略,但函数体可以为空 

 lambda表达式的使用:

第三个表达式时this时,可以省略

    //利用lambda表达式实现点击按钮关闭窗口QPushButton *btn2=new QPushButton("关闭",this);btn2->move(300,0);connect(btn2,&QPushButton::clicked,this,[=](){this->close();emit zt->hungry("烤腰子");btn2->setText("aaa");});

3.5Open Close控制实现案例

#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菜单栏:

QMenuBar *bar = menuBar();//创建菜单栏,菜单栏只能有一个setMenuBar(bar);//将菜单栏放入到窗口中QMenu * fileMenu=bar->addMenu("文件");    //创建菜单
QMenu * editMenu=bar->addMenu("编辑");    //返回的是QMenu *fileMenu->addAction("新建");//创建菜单项目,返回的是QAction *
fileMenu->addSeparator();//添加分隔线
fileMenu->addAction("打开");

4.2工具栏:

QToolBar *toolBar = new QToolBar(this);  //工具栏 ,可以有多个//将工具栏放在窗口中addToolBaraddToolBar(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状态栏:

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

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

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

4.5中心部件: 

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

4.6全部代码 

#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);//将工具栏放在窗口中addToolBaraddToolBar(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资源文件添加

1.将图片文件拷贝到项目文件下

2.创建一个新文件,右键项目->添加新文件->Qt->Qt Resource File->起名

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)");//返回值QStringqDebug()<<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转QStringui->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

然后新建一个C++类,名为mylabel(包含.h,.cpp) 

注意:mylabel类应继承QLabel

8.1鼠标进入事件enterEvent

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

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

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

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

8.2鼠标离开事件leaveEvent

8.2.1在mylabel.h中添加声明

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

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

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

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

8.3.1 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坐标,y坐标

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()        判断左右键 

左为Qt::LeftButton 右为Qt::RightButton 

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

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

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

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

8.3.5 设置鼠标追踪 

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

8.3.6 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格式化字符串   

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.定时器、分发器、过滤器、绘图

9.1定时器的第一种方式 

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

widget.h中写: 

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

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

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

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

 timerEvent的返回值是定时器的唯一标识可以和ev->timerId做比较

 widget.h中写:

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

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:间隔,单位是毫秒msid2=startTimer(2000);
}
void Widget::timerEvent(QTimerEvent *ev)
{if(ev->timerId()==id1){static int num =1;//label_2每隔1秒+1ui->label_2->setText(QString::number(num++));}if(ev->timerId()==id2){//label_3每隔2秒+1static int num2 =1;ui->label_3->setText(QString::number(num2++));}
}
Widget::~Widget()
{delete ui;
}

9.2定时器的第二种方式

9.2.1利用定时器的类  QTimer 

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

 9.2.2创建定时器对象

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

 9.2.3启动定时器 timer->start

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

9.2.4信号槽连接 

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

9.2.5暂停  timer->stop

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

9.3 事件分发器event

 用于事件分发,也可以做拦截操作,但是不建议

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转换为evQString 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转换为evQString 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读到的数据放入文本框

         //将读到的数据放入textEditui->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-8QFile file(path);//参数就是读取文件的路径//设置打开方式file.open(QIODevice::ReadOnly);//只读//QByteArray array = file.readAll();QByteArray array;while(!file.atEnd())//文件尾的条件{array += file.readLine();//按行读};//将读到的数据放入textEditui->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翻金币的案例

翻金币资源: https://pan.baidu.com/s/1EV-Wph01AKy69C3Orwqw2g#list/path=%2F

11.1创建项目  添加资源配置

        创建一个项目,然后将所需要的资源添加进文件内

11.2项目配置设置背景 大小 标题 背景 图标 

11.2.1配置大小、图标、标题、退出按钮

    //配置主场景//设置固定大小setFixedSize(320,588);//设置图标setWindowIcon(QIcon(":/res/Coin0001.png"));//设置标题setWindowTitle("翻金币主场景");//退出按钮的实现connect(ui->actionquit,&QAction::triggered,[=](){this->close();});

11.2.2配置背景 

    //重写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创建开始按钮

       11.3.1 封装自定义的按钮 MyPushButton

                 新建一个类为MyPushButton

                主场景创建开始按钮 

   //开始的按钮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构造函数(默认显示图片,按下后显示图片)

  //构造函数 参数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开始制作特效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创建选择关卡场景

 创建一个选择关卡场景类

        11.4.1点击开始按钮后延时进入到选择关卡场景

                主场景添加: 

    ClooseLevelScene * chooseScene = NULL;
    connect(startBtn,&MyPushButton::clicked,[=](){qDebug()<<"点击了开始";//做一个弹起的特效startBtn->zoom1();//做一个回弹特效startBtn->zoom2();//延时进入到选择关卡场景QTimer::singleShot(200,this,[=](){//进入到选择关卡场景中//将自身隐藏this->hide();//显示选择关卡场景chooseScene->show();});});

       11.4.2 配置选择关卡场景(设置背景 大小 标题 背景 图标) 

                配置选择关卡场景的相关设置 

  //配置选择关卡场景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();});

配置背景图: 

    //重写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创建返回按钮

    //返回按钮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返回关卡的返回按钮特效切换

    //重写按钮 按下  释放 事件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 开始场景与选择关卡场景的切换

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选择关卡按钮创建

11.5.1单个for循环创建矩阵 

 //创建选择关卡的按钮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按钮上设置显示关卡数

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翻金币场景的基本配置

新建类PlayScene,注意选择QmainWindow

11.6.1配置游戏场景(设置背景 大小 标题 背景 图标) 

与之前相同 

11.6.2实现返回按钮可以返回上一场景 

与之前相同 

11.6.3实现显示关卡的label

    //显示当前关卡数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创建金币类

 11.7.1先将金币的背景图案放入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创建MyCoin自定义金币按钮类

    //参数代表传入的金币路径 还是银币路径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()));
}

构造函数中那个传入默认显示的图片金币

11.7.3在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每个关卡的默认显示

引入dataConfig.h和dataConfig.cpp文件到项目中

在PlayScene中写了int gameArray[4][4]的数组  维护每个关卡的金币状态

初始化每个关卡的显示

11.9翻金币特效

 11.9.1给每个硬币加属性  posx  posy  bool flag

    //金币的属性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给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监听信号并翻转

//监听正面翻反面的信号  并且翻转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重置为1if(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重置为1if(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解决快速点击效果不好的问题

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

11.9.5点击硬币周围一起翻转

    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判断胜利

playsence中 添加iswin标志判断是否胜利 

    //是否胜利的标志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,再次点击,直接returnfor(int i = 0 ; i < 4 ; i++){for(int j = 0 ; j < 4 ; j++){coinBtn[i][j]->isWin=true;}}}

将iswin的判断添加进来,如果全部为true,直接return 

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

11.9.7胜利图片设置

    //胜利图片的显示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,再次点击,直接returnfor(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音效设置

 QSound所属模块 multimedia 需要加载.pro文件中

    QSound *startSound = new QSound(":/res/TapButtonSound.wav",this);startSound->setLoops(-1);//设置循环,-1为无限循环startSound->play();

11.9.9每个场景保持一个位置

 开始进入下一个场景:

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

 返回上一个场景,show之前写

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

 11.10项目打包及游戏扩展

 debug改为release并运行

找到.exe,放在文件夹里,打开该位置命令符

找到QT里的bin里的windeployqt

在命令行输入windeployqt 文件名.exe运行


http://chatgpt.dhexx.cn/article/v6ou3776.shtml

相关文章

pdflatex和xelatex的使用差别和建议

关于pdflatex和xelatex的区别的一些注意点 pdflatex 和xelatex分别是什么我遇到的一些问题 pdflatex 和xelatex分别是什么 pdflatex 和xelatex是latex编译中最常用的编译方式&#xff0c;而且效果一般都是比较好的。 PDFLaTeX命令&#xff1a;PDFTeX程序中的命令&#xff0c;用…

关于MAC解决jupyter中出现nbconvert failed/ xelatex not found on path报错

前言 开开心心的花了半个小时做完了2303的期中测试&#xff0c;结果在导出为pdf的时候提示我500错误&#xff0c;说明为nbconvert failed: xelatex not found on path&#xff0c;我当时就蒙了昂&#xff0c;不过还好考试时间是三个小时&#xff0c;还能浪浪&#xff0c;但是我…

【LaTex使用总结】LaTex,pdflatex,xelatex,xetex等的区别和关系

问题是这样产生的&#xff0c;从本科毕设开始接触LaTex起&#xff0c;使用现成的模板进行编译生成操作&#xff0c;一步步按指示操作也从未深究。 后来使用word较多&#xff0c;LaTex经常是简单模板&#xff0c;也渐渐对LaTex的细节不再感兴趣&#xff0c;近期又开始用LaTex撰写…

pyplot 使用 latex 报错:xelatex not found……

错误提示 发生异常: RuntimeError xelatex not found. Install it or change rcParams[pgf.texsystem] to an available TeX implementation. 原始参数&#xff1a; plt.rcParams.update({"pgf.texsystem": "xelatex","text.usetex": True,# u…

Winedt为什么可以用pdfLaTex编译中文(pdfLaTex和XeLaTex的使用)

文章目录 Winedt为什么可以用pdfLaTex编译中文查看Winedt的默认编译器&#xff1a; 1.XeLaTex和pdfLaTex的关系2.Winedt中使用pdfLaTex编译中文的tex3.原因4.验证 Winedt为什么可以用pdfLaTex编译中文 前言&#xff1a;如果你只是想用Winedt实现LaTex中英混排那么可以直接选择…

recipe terminated with fatal error: spawn xelatex enoent.

vscode配置latex的小问题 问题产生的原因是环境变量没有配置好。所以只需要把环境变量配置好就可以了。 1、 打开textlive安装的路径&#xff08;…\textlive\2022\bin\win32&#xff09;&#xff0c;比如我的就是C:\texlive\2022\bin\win32 2、编辑环境变量&#xff1a; 编…

TeXstudio报错: fwrite: Broken pipe xelatex.exe

错误&#xff1a; 解决方法&#xff1a; 选项->设置TeXstudio 默认编译器换成PdfLaTex&#xff1a; 问题解决。

CTEX编译Xelatex以及如何更新Miktex

1.现在很多科研人员都喜欢用latex来写文章&#xff0c;主要是latex有了模板之后排版较简单&#xff0c;而且参考文献比较容易生成&#xff0c;不需要再去排版。本人自己比较喜欢使用CTEX&#xff0c;这个得看个人习惯使用吧。有很多同胞在使用CTEX 时可能会遇到无法编译Xelatex…

linux下latex使用教程,LaTeX使用--XeLaTeX入门基础(二)

主机平台&#xff1a;Gentoo Linux 11.2 内核版本&#xff1a;Linux Kernel 3.2.1 编译环境&#xff1a;XeTeX 3.1415926-2.3-0.9997.5 (TeX Live 2011) 相关阅读 主机平台&#xff1a;Gentoo Linux 11.2 内核版本&#xff1a;Linux Kernel 3.2.1 编译环境&#xff1a;XeTeX 3.…

TeXworks 设置成默认用XeLaTeX排版

TeXworks 设置成默认用XeLaTeX排版 在用Texlive2020中,自身自带的编辑器每次都是默认以pdfLaTeX的方式进行排版 因为pdfLaTex在排版中文的时候容易乱码和报错, 用XeLaTeX排版就不会,为了方便就将它设置为一打开编辑器就是以XeLaTeX 方式排版 一打开就是这样子 首先在编辑器页面…

解决XeLaTex编译后中文出现乱码的问题

最近想用LaTex做简历&#xff0c;但是在做中文简历的时候&#xff0c;出现乱码的情况&#xff0c;网上查了很多解决方法&#xff0c;最后成功解决了&#xff0c;在这里总结分享一下。 先建立一个tex文件&#xff0c;输入一下格式的文件&#xff0c;注意加入\usepackage{CTEX} …

Latex、XeLatex无法加粗

XeLaTeX是新的Unicode版本&#xff0c;内建支持Unicode(UTF-8)&#xff0c;可以调用操作系统的字体。但是在使用的时候也可能会出现许多问题&#xff0c;例如我最近使用的时候字体就一直无法显示粗体&#xff0c;但是运行的时候不报错。 原因有可能是你的系统里面缺少模板指定…

配置中文XeLaTex环境

本人初始时懒人一键使用了CTex安装&#xff0c;但无奈写中文论文时版本太低不支持使用的模板&#xff0c;所以开始自行配置TexLiveWinEdtSumatraPDF的环境。【TeXworks个人觉得真的不太好用 其中使用TexLive时遇到的一些问题及解决方案如下&#xff1a; fontspec.cfg: Erroneo…

VSCode Latex Workshop 设置 XeLatex 编译

前言 VSCode LatexWorkshop 是非常方便的组合&#xff0c;而对于中文文档&#xff0c;pdfLatex 引擎的支持很差&#xff0c;很多时候需要使用 XeLatex 引擎编译&#xff0c;但是总是莫名其妙各种报错。用下面的 magic 语句也无济于事。 % !TEX program xelatex 本篇介绍通…

overleaf 改为XeLatex怎么操作

文章目录 overleaf 改为XeLatex怎么操作 overleaf 改为XeLatex怎么操作 想将overleaf中的编译器改为XeLatex&#xff0c;搜索后也没有发现太好的回答&#xff0c;解决方法如下 点击菜单选项&#xff0c;然后就可以对overleaf进行设置了 效果如下&#xff1a;

XeLaTeX: 支持现代字体 LaTeX 编译器

XeLaTeX: 支持现代字体 LaTeX 编译器 原  文&#xff1a;XeLaTeX 译  者&#xff1a;Xovee 翻译时间&#xff1a;2023年2月21日 文章目录 XeLaTeX: 支持现代字体 LaTeX 编译器介绍基础&#xff1a;Times New Roman为不同的LaTeX模块设置不同的字体Overleaf中的字体安装在O…

java中如何做展示 IP 属地的功能(至尊典藏版)

目录 前言 1、HttpServletRequest 获取 IP 2、Ip2region 3、99.9%准确率 4、多查询客户端的支持 5、Ip2region V2.0 特性 6、ip2region xdb java 查询客户端实现 7、IDEA中做个测试 8、编译测试程序 9、查询测试 10、bench 测试 前言 细心的朋友应该会发现&#xff…

【获取IP归属地】Java如何实现通过IP获取IP归属地 [离线+在线](附代码,2023年亲测有效)

【写在前面】 编撰这篇文章还得从之前做安全业务需求说起&#xff0c;我们都知道安全攻击都是在某台客户机上执行某些恶意操作&#xff08;sql注入&#xff0c;DoS/DDoS攻击&#xff09;&#xff0c;致使服务端响应异常崩溃亦或响应数据被篡改&#xff0c;那么怎么去阻止这些东…

1.Java获取本机IP地址,主机名,域名

1.如何在程序中获取本机的IP地址&#xff0c;主机名以及域名呢&#xff1f; 在java中&#xff0c;我们可以利用java.net.InetAddress这个类来实现。 InetAddress 类提供了操作 IP 地址的各种方法。该类本身没有构造方法&#xff0c;而是通过调用相关静态方法获取实例。 InetA…

Java通过Ip2region实现IP定位

我们在一些短视频平台上可以看到,视频作者或评论区可以显示IP地址,这其实就是根据IP获取到的我们可以通过一些在线网站就可以看到我们当前的公网IP和IP定位,最近有个需求也需要通过请求获取客户端的IP和IP的定位,于是通过一系列的百度,最终选择使用Ip2region这个工具库来进行定…