学习笔记
最新QT从入门到实战完整版|传智教育_哔哩哔哩_bilibili
目录
3.3.7信号的参数个数可以比槽函数参数个数多,但是需要一一对应,反之不可
2.在新建的.ui文件中设置QSpinBox和QSlider两个控件
9.1.1利用事件 void timerEvent(QTimerEvent *ev)
9.3.2 返回值若是true,则代表用户处理这个时间,不向下分发了
11.4.2 配置选择关卡场景(设置背景 大小 标题 背景 图标)
11.6.1配置游戏场景(设置背景 大小 标题 背景 图标)
11.9.1给每个硬币加属性 posx posy bool flag
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)->头文件声明->源文件槽函数实现
头文件声明时:
3.1.1自定义信号:
自定义信号,写到signals下
返回值是void,只需要声明,不需要实现
可以有参数,可以重载
signals:
void hungry();
3.1.2自定义槽:
早期版本qt,必须写到public slots,高级版本可以下到public或者全局函数下
返回值是void,需要声明,也需要实现
可以有参数,可以发生重载
public slot:
void treat();
>源文件的槽函数实现:
void Student::treat()
{
qDebug()<<"请老师吃饭";
}
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();//触发的关键字:emit
emit 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); //工具栏 ,可以有多个
//将工具栏放在窗口中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状态栏:
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);
//将工具栏放在窗口中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资源文件添加
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)");//返回值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
然后新建一个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:间隔,单位是毫秒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定时器的第二种方式
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转换为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翻金币的案例
翻金币资源: 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重置为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解决快速点击效果不好的问题
//重写 按下 和 释放
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,再次点击,直接return
for(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,再次点击,直接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音效设置
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运行