学习笔记
最新QT从入门到实战完整版|传智教育_哔哩哔哩_bilibili
目录
3.3.7信号的参数个数可以比槽函数参数个数多,但是需要一一对应,反之不可
2.在新建的.ui文件中设置QSpinBox和QSlider两个控件
9.1.1利用事件 void timerEvent(QTimerEvent *ev)
9.3.2 返回值若是true,则代表用户处理这个时间,不向下分发了
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
10 QFile Read and write operations on files
10.1.1 Signal slot connection button and file
10.1.2 Put the path in lineEdit
10.1.4 Opening files in read-only mode
10.1.7 Put the read data into the text box
10.1.8 Need to convert format to read
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.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.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.1 Add attribute posx posy bool flag to each coin
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.7 Victory Picture 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