1 Qt简介
跨平台图形界面引擎
优点:
a.跨平台
b.接口简单,容易上手
c.一定程度上简化了内存回收
2 创建第一个Qt程序
第一步:文件 --> New Project 或 创建项目
第二步: Application(Qt) --> Qt Widgets Application
第三步:设置项目名称、保存路径
名称:不能有中文,不能有空格
路径:不能有中文路径
第四步:选择“qmake”
第五步:选择Bass Class,设置类名
默认创建有窗口类,基类有三种选择:QWidget、QMainWindow、QDialog
QWidget是父类,QMainWindow和QDialog继承QWidget;
QWidget创建完成后只有一个空窗口;
QMainWindow创建完成后有状态栏、菜单栏、工具、状态;
QWidget创建完成后是对话框;
第六步:选择默认Kit
第七步:编写代码
QApplication a 应用程序对象,有且仅有一个
myWidget w; 实例化窗口对象
w.show() 调用show函数,显示窗口
return a.exec() 让应用程序对象进入消息循环机制中,代码阻塞到当前行
3 按钮控件常用API
第一步:定位项目名右键“添加新文件”
第二步:C/C++ --> C++ Class
第三步:选择Bass Class,设置类名
第四步:完成
01_QtProject
第五步:编写代码
01_QtProject.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mypushbutton.cpp \
mywidget.cpp
HEADERS += \
mypushbutton.h \
mywidget.h
FORMS += \
mywidget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mypushbutton.h
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QPushButton>
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
//构造
explicit MyPushButton(QWidget *parent = nullptr);
//析构
~MyPushButton();
signals:
};
#endif // MYPUSHBUTTON_H
mypushbutton.cpp
#include "mypushbutton.h"
#include <QDebug>
MyPushButton::MyPushButton(QWidget *parent)
: QPushButton{parent}
{
qDebug() << "我的按钮类构造调用";
}
MyPushButton::~MyPushButton()
{
qDebug() << "我的按钮类析构调用";
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget> //包含头文件 QWidget 窗口类
QT_BEGIN_NAMESPACE
namespace Ui {
class MyWidget;
}
QT_END_NAMESPACE
class MyWidget : public QWidget
{
Q_OBJECT //Q_OBJECT宏,允许类中使用信号和槽的机制
public:
MyWidget(QWidget *parent = nullptr); //构造函数,有参构造
~MyWidget(); //析构函数
private:
Ui::MyWidget *ui;
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPushButton> //按钮控件的头文件
#include "mypushbutton.h"
//命名规范
//类名 首字母大写,单词和单词之间首字母大写
//函数名 变量名称 首字母小写,单词和单词之间首字母大写
//快捷键
//注释 ctrl+/
//运行 ctrl+r
//编译 ctrl+b
//字体缩放 ctrl+鼠标滚轮
//查找 ctrl+f
//整行移动 ctrl+shift+↑或者↓
//帮助文档 F1
//自动对齐 ctrl+i
//同名之间的.h和.cpp切换 F4
//
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MyWidget)
{
ui->setupUi(this);
//创建一个按钮
QPushButton* btn = new QPushButton;
//btn->show(); //show以循环方式弹出窗口控件
//让btn对象 依赖在MyWidget窗口中
btn->setParent(this);
//显示文本
btn->setText("第一个按钮");
//创建第二个按钮 按照控件的大小创建窗口
QPushButton* btn2 = new QPushButton("第二个按钮", this);
//移动btn2按钮
btn2->move(100,100);
//设置按钮大小
btn2->resize(200,200);
//重置窗口大小
resize(600,400); //可以拖动窗口改变大小
//设置固定窗口大小
setFixedSize(600,400); //设置后无法拖动窗口改变大小
//设置窗口标题
setWindowTitle("第一个窗口");
//创建一个自己的按钮对象
MyPushButton* myBtn = new MyPushButton;
myBtn->setText("我自己的按钮");
myBtn->move(300,0);
myBtn->setParent(this);
//需求 点击我的按钮 关闭窗口
//connect(信号的发送者,发送的信号(函数的地址),信号的接收者,处理的槽函数)
//connect(myBtn, &QPushButton::clicked, this, &MyWidget::close);
connect(myBtn, &QPushButton::clicked, this, &QWidget::close);
}
MyWidget::~MyWidget()
{
delete ui;
qDebug() << "myWidget的析构调用";
}
main.cpp
#include "mywidget.h"
#include <QApplication> //包含一个应用程序类的头文件
//main程序入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{
//a应用程序对象,在Qt中,应用程序对象,有且仅有一个
QApplication a(argc, argv);
//窗口对象 MyWidget父类 -> QWidget
MyWidget w;
//窗口对象 默认不会显示,必须要调用show方法显示窗口
w.show();
//让应用程序对象进入消息循环
//让代码阻塞到这行
return a.exec();
}
运行结果
创建:QPushButton* btn = new QPushButton
设置父亲:setParent(this)
设置文本:setText("文字")
设置位置:move(宽,高)
重新指定窗口大小:resize(宽,高)
设置窗口标题:setWindowTitle("标题")
设置窗口固定大小:setFixedSize(宽,高)
4 对象树
当创建的对象在堆区间时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作,将对象放入到对象树中
优点:一定程度上简化了内存回收机制
5 Qt中的坐标
左上角为0,0点
x以右为正方向
y以下为正方向
6 信号和槽
连接函数:connect(信号的发送者,发送的信号(函数地址),信号的接受者,处理的槽函数(函数地址))
松散耦合
点击按钮,关闭窗口:connect(btn, &QPushButton::click, this, &QWidget::close);
自定义信号:
普通函数,不需要实现(使用signals关键字声明)——只有函数声明
没有返回值,void类型函数
需要声明,不需要实现
可以有参数,可以重载
自定义槽函数:
返回void
需要声明,也需要实现
可以有参数,可以重载
写到public slot下,或者public,或者全局函数
当自定义信号和槽出现重载:
需要利用函数指针,明确指向函数的地址
void(Teacher::*tSignal)(QString)=&Teacher::hungry;
QString转成char*:.ToUtf8()转为QByteArray、.Data()转为char*
信号可以连接信号
断开信号disconnect
拓展:
信号可以连接信号
一个信号可以连接多个槽函数
多个信号可以连接同一个槽函数
信号和槽函数的参数,必须类型一一对应
信号的参数个数,可以多余槽函数的参数个数
信号槽可以断开连接disconnect
Qt4版本写法:
connect(信号的发送者,发送的信号 SIGNAL(信号),信号接受者,槽函数 SLOT(槽函数))
优点:参数直观
缺点:编译器不会检测参数类型
lambda表达式:
[]标识符 匿名函数、=值传递、&引用传递
()参数
{}实现体
mutable修饰值传递变量,可以修改拷贝出的数据,改变不了主体
返回值 []()->int{}
02_SignalAndSlot信号和槽
02_SignalAndSlot.por
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
student.cpp \
teacher.cpp \
widget.cpp
HEADERS += \
student.h \
teacher.h \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:
//自定义槽函数,写在public slots下
//返回void
//需要声明,也需要实现
//可以有参数,可以重载
void treat();
//重载
void treat(QString foodName);
};
#endif // STUDENT_H
student.cpp
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent)
: QObject{parent}
{}
void Student::treat()
{
qDebug() << "请老师吃饭";
}
void Student::treat(QString foodName)
{
//直接使用foodName,输出的foodName有双引号"",去除双引号QString->char*
//QString->char*:先将QString转成QByteArray(.toUtf8()),再转char*()
qDebug() << "请老师吃饭,老师要吃:" << foodName.toUtf8().data();
}
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号 写到signals下
//返回值是void,只需要声明,不需要实现
//可以有参数,可以重载
void hungry();
void hungry(QString foodName);
public slots:
};
#endif // TEACHER_H
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent)
: QObject{parent}
{}
//重载不需要实现
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "teacher.h"
#include "student.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
void classIsOver();
void classIsOver(QString foodName);
private:
Ui::Widget *ui;
Teacher* zt;
Student* st;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
//Teacher 类 老师类
//Student 类 学生类
//下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个老师对象
this->zt = new Teacher(this);
//创建一个学生对象
this->st = new Student(this);
//老师饿了,学生请客的连接
//connect(zt, &Teacher::hungry, st, &Student::treat);
//调用下课函数
//classIsOver();
//连接不带参数的信号和槽
void(Teacher::*teacherSignal1)(void) = &Teacher::hungry;
void(Student::*studentSlot1)(void) = &Student::treat;
connect(zt, teacherSignal1, st, studentSlot1);
classIsOver();
//连接带参数的 信号和槽
void(Teacher::*teacherSignal2)(QString) = &Teacher::hungry;
void(Student::*studentSlot2)(QString) = &Student::treat;
connect(zt, teacherSignal2, st, studentSlot2);
classIsOver("宫保鸡丁");
//点击一个下课的按钮,再触发下课
QPushButton* btn1 = new QPushButton("下课1", this);
//点击按钮,触发下课
void(Widget::*classIsOverSlot1)( ) = &Widget::classIsOver;
connect(btn1, &QPushButton::clicked, this, classIsOverSlot1);
//断开信号
disconnect(zt, teacherSignal2, st, studentSlot2);
disconnect(btn1, &QPushButton::clicked, this, classIsOverSlot1);
//拓展
//1、信号是可以连接信号
//2、一个信号可以连接多个槽函数
//3、多个信号 可以连接 同一个槽函数
//4、信号和槽函数的参数必须类型一一对应
//5、信号的参数个数 可以多余槽函数的参数个数
//Qt4版本以前的信号和槽连接方式
//利用Qt4信号槽 连接无参版本
//Qt4版本 底层SIGNAL("hungry") SLOT("treat")
connect(zt, SIGNAL(hungry()), st, SLOT(treat()));
//Qt4版本优点:参数直观;缺点:类型不做检测
//Qt5以上支持Qt4的版本写法,反之不支持
//lambda表达式
mutable关键字,用于修饰值传递的变量,修改的是拷贝,而不是实体
QPushButton* myBtn1 = new QPushButton("按钮1", this);
QPushButton* myBtn2 = new QPushButton("按钮2", this);
myBtn1->move(300,0);
myBtn2->move(300,100);
int m=10;
connect(myBtn1, &QPushButton::clicked, this, [m]() mutable { m=100+10; qDebug()<<m;});
qDebug()<<m;
connect(myBtn2, &QPushButton::clicked, this, [=]() mutable { qDebug()<<m;});
qDebug()<<m;
QPushButton* closeBtn = new QPushButton("关闭",this);
closeBtn->move(300,200);
connect(closeBtn, &QPushButton::clicked, this, [](){
this->close();
});
//重置窗口大小
this->resize(600, 400);
}
Widget::~Widget()
{
delete ui;
}
void Widget::classIsOver()
{
//下课函数,调用后触发老师饿了
emit zt->hungry();
}
void Widget::classIsOver(QString foodName)
{
emit zt->hungry(foodName);
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
7 QMainWindow
1.菜单栏,最多有一个
QMenuBar* bar = new MenuBar();
设置到窗口中 setMenuBar(bar)
QMenu* fileMenu = bar->addMenu("文件"); //创建菜单
QAction* newAction = fileMenu->addAction("新建"); //创建菜单项
添加分割线 fileMenu->addSeparator();
2.工具栏,可以有多个
QToolBar* toolBar = new QToolBar(this);
addToolBar(默认停靠区域,toolBar); //Qt::LeftToolBarArea
设置后期停靠区域,设置浮动,设置移动
添加菜单项,或者添加小控件
3.状态栏,最多一个
QStatusBar* stBar = new QStatusBar();
设置到窗口中 setStatuasBar(stBar);
setBar->addWidget(label); //放左侧信息
setBar->addPermanentWidget(label2); //放右侧信息
4.铆接部件 浮动窗口 可以多个
QDockWidget
addDockWidget(默认停靠区域,浮动窗口指针)
设置后期停靠区域
5.设置核心部件 只能一个
03_MainWindow
03_MainWindow.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>
#include <QTextEdit>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//重置窗口大小
resize(600,400);
//菜单栏 最多只能有一个
//菜单栏创建
QMenuBar* bar = menuBar();
//将菜单栏放入到窗口中
setMenuBar(bar);
//创建菜单
QMenu* fileMenu = bar->addMenu("文件");
QMenu* openMenu = bar->addMenu("编辑");
//创建菜单项
QAction* newAction = fileMenu->addAction("新建");
QAction* openAction = fileMenu->addAction("打开");
//添加分割线
fileMenu->addSeparator();
QAction* saveAction = fileMenu->addAction("保存");
//工具栏,可以有多个,工具栏默认可以移动,上下左右都可以停靠;工具栏默认可以浮动
QToolBar* toolBar = new QToolBar(this);
//工具栏默认在上面
//addToolBar(toolBar);
//工具栏放在左侧
addToolBar(Qt::LeftToolBarArea, toolBar);
//只允许左右停靠
toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
//设置浮动
toolBar->setFloatable(false);
//设置移动
toolBar->setMovable(false);
//工具栏中可以设置内容
toolBar->addAction(newAction);
toolBar->addAction(openAction);
//添加分割线
toolBar->addSeparator();
toolBar->addAction(saveAction);
//工具栏中添加控件
QPushButton* btn = new QPushButton("aaa", this);
toolBar->addWidget(btn);
//状态栏,最多只有一个
QStatusBar* staBar = new QStatusBar();
//设置到窗口
setStatusBar(staBar);
//放标签控件
QLabel* label1 = new QLabel("提示信息", this);
staBar->addWidget(label1);
QLabel* label2 = new QLabel("右侧提示信息", this);
staBar->addPermanentWidget(label2);
//浮动窗口 可以有多个
QDockWidget* dockWidget = new QDockWidget("浮动窗口", this);
this->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
//设置后期停靠区域,只允许上下
dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
//设置中心部件,最多只能有一个
QTextEdit* edit = new QTextEdit(this);
this->setCentralWidget(edit);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
运行结果
8 资源文件
04_QtSource
04_QtSource.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
QAction无法在ui中直接输入中文,输入new后,会生成actionnew,可以在属性中修改text为“新建”;QAction右键可以“添加分隔符”,分隔符插入后可以拖拽;
可以拖动下窗口的action放到toolbar中;toolbar可以右键添加分隔符
铆接部件,可以设置是否浮动,设置停靠位置
action可以设置图标
第一步:将图片文件 拷贝到项目位置下
第二步:右键项目 --> 添加新文件
第三步:Qt --> Qt Resource File
第四步:给资源文件起别名,res生成 res.qrc
第六步:open in editor 编辑资源
第七步:添加前缀 添加文件
第八步:使用":+前缀名+文件名"
04_QtSource.pro
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>501</width>
<height>321</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>文件</string>
</property>
<addaction name="actionnew"/>
<addaction name="separator"/>
<addaction name="actionopen"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>编辑</string>
</property>
</widget>
<addaction name="menu"/>
<addaction name="menu_2"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="mainToolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionnew"/>
<addaction name="separator"/>
<addaction name="actionopen"/>
</widget>
<widget class="QDockWidget" name="dockWidget">
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents"/>
</widget>
<action name="actionnew">
<property name="text">
<string>新建</string>
</property>
</action>
<action name="actionopen">
<property name="text">
<string>打开</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
mianwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//ui->actionNew->setIcon(QIcon("D://Image//actionNew.png"));
//使用添加Qt资源 ":+前缀名+文件名"
ui->actionnew->setIcon(QIcon(":/Image/new.jpg"));
ui->actionopen->setIcon(QIcon(":/Image/open.jpg"));
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>501</width>
<height>321</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>文件</string>
</property>
<addaction name="actionnew"/>
<addaction name="separator"/>
<addaction name="actionopen"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>编辑</string>
</property>
</widget>
<addaction name="menu"/>
<addaction name="menu_2"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="mainToolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionnew"/>
<addaction name="separator"/>
<addaction name="actionopen"/>
</widget>
<widget class="QDockWidget" name="dockWidget">
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents"/>
</widget>
<action name="actionnew">
<property name="text">
<string>新建</string>
</property>
</action>
<action name="actionopen">
<property name="text">
<string>打开</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
9 对话框
分类:模态对话框、非模态对话框
模态对话框:不可以对其他窗口进行操作,阻塞
QDialog dlg1(this);
dlg1.exec();
非模态对话框:可以对其他窗口进行操作
防止一闪而过,创建到堆区
QDialog* dlg2 = new QDialog(this);
dlg2->show();
dlg2->setAttribute(Qt::WA_DeleteOnClose);
消息对话框:
QMessageBox静态成员函数,创建对话框
错误、信息、提问、警告
提问对话框参数:参数1:父亲;参数2:标题;参数3:提示内容;参数4:按键类型;参数5:默认关联回车的按键
返回值也是StandardButton类型,利用返回值判断用户的输入
颜色对话框 QColorDialog::getColor
文件对话框 QFileDialog::getOpenFileName(父亲,标题,默认路径,过滤,文件)
字体对话框 QFontDialog::getFont
05_QDialog.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#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, [this](){
//对话框分类:模态对话框(不可以对其他窗口进行操作)、非模态对话框(可以对其他窗口进行操作)
//创建模态对话框
//模态对话框有阻塞的功能
QDialog dlg1(this);
dlg1.resize(200,100);
dlg1.exec();
qDebug() << "模态对话框弹出了";
//创建非模态对话框
QDialog* dlg2 = new QDialog(this);
dlg2->resize(100,100);
dlg2->show();
dlg2->setAttribute(Qt::WA_DeleteOnClose);
qDebug() << "非模态对话框弹出来了";
//消息对话框(错误)
QMessageBox::critical(this, "critical", "错误");
//消息对话框(信息)
QMessageBox::information(this, "info", "信息");
//消息对话框(提问)
//参数1:父亲;参数2:标题;参数3:提示内容;参数4:按键类型;参数5:默认关联回车的按键
int res = QMessageBox::question(this, "question", "提问", QMessageBox::Save|QMessageBox::Cancel, QMessageBox::Cancel);
if (res == QMessageBox::Save){
qDebug() << "选择的是保存";
}
else{
qDebug() << "选择的是取消";
}
//消息对话框(警告)
QMessageBox::warning(this, "warning", "警告");
//颜色对话框
QColor color = QColorDialog::getColor(QColor(255,0,0));
qDebug() << "r = " << color.red() << " g = " << color.green()
<< " b = " << color.blue();
//文件对话框
//参数1:父亲;参数2:标题;参数3:默认打开路径;参数4:过滤文件格式
//返回值是 选取的路径
QString sFile = QFileDialog::getOpenFileName(this, "打开文件", "D://Desktop", "(*.txt)");
qDebug() << sFile;
//字体对话框
bool flag = false;
QFont font = QFontDialog::getFont(&flag, QFont("宋体", 36), this, "选择字体");
qDebug() << "字体:" << font.family().toUtf8().data() << ",字号:" << font.pointSize()
<< ",是否加粗:" << font.bold() << ",是否倾斜:" << font.italic();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>文件</string>
</property>
<addaction name="actionnew"/>
<addaction name="separator"/>
<addaction name="actionopen"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>新建</string>
</property>
</widget>
<addaction name="menu"/>
<addaction name="menu_2"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionnew"/>
<addaction name="separator"/>
<addaction name="actionopen"/>
</widget>
<action name="actionnew">
<property name="text">
<string>新建</string>
</property>
</action>
<action name="actionopen">
<property name="text">
<string>打开</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
10 界面布局
实现登陆窗口
利用布局方式给窗口进行美化
选取widget进行布局,水平布局、垂直布局、栅格布局
给用户名、密码、登陆、退出按钮进行布局
默认窗口和控件之间有9间隙,可以调整layoutLeftMargin
利用弹簧进行布局
弹簧默认是Expanding,可以设置默认值Fixed。
06_Layout.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>300</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>300</height>
</size>
</property>
<property name="windowTitle">
<string>登陆窗口</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>用户名:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>密 码:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_2">
<property name="echoMode">
<enum>QLineEdit::EchoMode::Password</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widget_3" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>退出</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>登陆</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
11 控件
1 按钮组
QPushButton 常用按钮;
QToolButton 工具按钮,用于显示图片,如想显示文字,需修改风格toolButtonStyle,凸起风格autoRaise;
radioButton 单选按钮,设置默认 ui->radioButton->setChecked(true);
checkbox多选按钮,监听状态,2是选中,1是半选,0是未选中
2 QListWidget 列表容器
QListWidgetItem *item = new QListWidgetItem("一行内容");
ui->listWidget->addItem(item);
设置居中方式 item->setTextAlignment(Qt::AlignHCenter);
可以利用addItems一次性添加多个item
3 QTreeWidget 树控件
设置头 ui->treeWidget->setHeaderLabels(QStringList() << "英雄" << "英雄介绍");
创建根节点 QTreeWidgetItem* liItem = new QTreeWidgetItem(QStringList() << "力量");
添加根节点到树控件上 ui->treeWidget->addTopLevelItem(liItem);
添加子节点 liItem->addChild(li1);
4 QTableWidget 表格控件
设置列数 ui->tableWidget->setColumnCount(3);
设置水平表头 ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄");
设置行数 ui->tableWidget->setRowCount(5);
设置正文 ui->tableWidget->setItem(i, 0, new QTableWidgetItem(nameList[i]));
07_Qt_Control
07_Qt_Control.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
src.qrc
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置单选按钮,男 默认选中
ui->radioButtonMan->setChecked(true);
//选中 女 后,打印信息
connect(ui->radioButtonWoman, &QRadioButton::clicked, [=](){
qDebug() << "选中了女";
});
//多选按钮 2是选择 0是未选中 1是半选状态(需设置checkBox的tristate)
connect(ui->checkBox, &QCheckBox::stateChanged, [=](int state){
qDebug() << state;
});
//利用listWidget写诗
QListWidgetItem* item1 = new QListWidgetItem("锄禾日当午");
//将一行诗放入到listWidget控件中
ui->listWidget->addItem(item1);
//设置对齐方式
item1->setTextAlignment(Qt::AlignHCenter);
QListWidgetItem* item2 = new QListWidgetItem("汗滴禾下土");
ui->listWidget->addItem(item2);
QListWidgetItem* item3 = new QListWidgetItem("谁之盘中餐");
ui->listWidget->addItem(item3);
QListWidgetItem* item4 = new QListWidgetItem("粒粒皆辛苦");
ui->listWidget->addItem(item4);
//QStringList QList<QString>
QStringList list;
list << "鹅鹅鹅" << "曲项向天歌" << "白毛浮绿水" << "红掌拨清波";
ui->listWidget->addItems(list);
//treeWidget树控件使用
//设置水平头
ui->treeWidget->setHeaderLabels(QStringList() << "英雄" << "英雄介绍");
QTreeWidgetItem* liItem = new QTreeWidgetItem(QStringList() << "力量");
//加载顶层的节点
ui->treeWidget->addTopLevelItem(liItem);
QTreeWidgetItem* minItem = new QTreeWidgetItem(QStringList() << "敏捷");
ui->treeWidget->addTopLevelItem(minItem);
QTreeWidgetItem* zhiItem = new QTreeWidgetItem(QStringList() << "智力");
ui->treeWidget->addTopLevelItem(zhiItem);
//追加子节点
QTreeWidgetItem* li1 = new QTreeWidgetItem(QStringList() << "刚被猪" << "前排坦克,能在吸收伤害的同时造成可观的范围输出");
liItem->addChild(li1);
QTreeWidgetItem* li2 = new QTreeWidgetItem(QStringList() << "船长" << "前排坦克,能肉能控场的全能英雄");
liItem->addChild(li2);
QTreeWidgetItem* min1 = new QTreeWidgetItem(QStringList() << "月骑" << "中排物理输出,可以使用分裂利刃攻击多个目标");
minItem->addChild(min1);
QTreeWidgetItem* min2 = new QTreeWidgetItem(QStringList() << "小鱼人" << "前排战士,擅长偷取敌人的属性来增强自身战力");
minItem->addChild(min2);
QTreeWidgetItem* zhi1 = new QTreeWidgetItem(QStringList() << "死灵法师" << "前排法师坦克,魔法抗性较高,拥有治疗技能");
zhiItem->addChild(zhi1);
QTreeWidgetItem* zhi2 = new QTreeWidgetItem(QStringList() << "巫医" << "后排辅助法师,可以使用奇特的巫术诅咒敌人与治疗队友");
zhiItem->addChild(zhi2);
//TableWidget 表格控件
//设置列数
ui->tableWidget->setColumnCount(3);
//设置水平表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄");
//设置行数
ui->tableWidget->setRowCount(5);
//设置正文
QStringList nameList;
nameList << "张三" << "李四" << "王五";
QStringList sexList;
sexList << "男" << "女" << "男";
for (int i=0;i<3;i++){
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(nameList[i]));
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(sexList[i]));
//int 转 QString
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(QString::number(i+10)));
}
}
Widget::~Widget()
{
delete ui;
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>794</width>
<height>531</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>40</x>
<y>30</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>登陆</string>
</property>
</widget>
<widget class="QToolButton" name="toolButton">
<property name="geometry">
<rect>
<x>50</x>
<y>100</y>
<width>71</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>新建</string>
</property>
<property name="icon">
<iconset resource="src.qrc">
<normaloff>:/Image/new.jpg</normaloff>:/Image/new.jpg</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonStyle::ToolButtonTextUnderIcon</enum>
</property>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>180</y>
<width>67</width>
<height>96</height>
</rect>
</property>
<property name="title">
<string>性别</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="radioButtonMan">
<property name="text">
<string>男</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonWoman">
<property name="text">
<string>女</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="groupBox_2">
<property name="geometry">
<rect>
<x>90</x>
<y>180</y>
<width>81</width>
<height>96</height>
</rect>
</property>
<property name="title">
<string>婚否</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="radioButton_3">
<property name="text">
<string>已婚</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_4">
<property name="text">
<string>未婚</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="groupBox_3">
<property name="geometry">
<rect>
<x>190</x>
<y>20</y>
<width>122</width>
<height>156</height>
</rect>
</property>
<property name="title">
<string>问卷调查</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>价格实惠</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_2">
<property name="text">
<string>口感好</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_3">
<property name="text">
<string>服务到位</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_4">
<property name="text">
<string>老板娘好</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>290</y>
<width>193</width>
<height>28</height>
</rect>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>330</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
<widget class="QTreeWidget" name="treeWidget">
<property name="geometry">
<rect>
<x>330</x>
<y>10</y>
<width>401</width>
<height>211</height>
</rect>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
<widget class="QTableWidget" name="tableWidget">
<property name="geometry">
<rect>
<x>330</x>
<y>230</y>
<width>401</width>
<height>221</height>
</rect>
</property>
</widget>
</widget>
<resources>
<include location="src.qrc"/>
</resources>
<connections/>
</ui>
运行结果:
12 其他控件
stackWidget 栈控件
ui->stackWidget->setCurrentIndex(1);
comboBox 下拉框
ui->comboBox->addItem("奔驰");
QLabel 显示图片
ui->lbl_Image->setPixmap(QPixmap(":/Image/butterfly.png"))
QLabel 显示动图 gif图片
ui->lbl_Image->setMove(movie);
movie->start();
08_OtherControl.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//栈控件使用
//设置默认定位 scrollArea
ui->stackedWidget->setCurrentIndex(0);
//scrollArea按钮
connect(ui->btn_scrollArea, &QPushButton::clicked, [=](){
ui->stackedWidget->setCurrentIndex(0);
});
//toolBox按钮
connect(ui->btn_toolBox, &QPushButton::clicked, [=](){
ui->stackedWidget->setCurrentIndex(1);
});
//tabWidget按钮
connect(ui->btn_tabWidget, &QPushButton::clicked, [=](){
ui->stackedWidget->setCurrentIndex(2);
});
//下拉框
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("宝马");
ui->comboBox->addItem("拖拉机");
//点击按钮 comboBox选中拖拉机
connect(ui->btn_select, &QPushButton::clicked, [=](){
ui->comboBox->setCurrentIndex(2);
//ui->comboBox->setCurrentText("拖拉机");
});
}
Widget::~Widget()
{
delete ui;
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QStackedWidget" name="stackedWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>271</width>
<height>491</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_4">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>-353</y>
<width>230</width>
<height>820</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_6">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_7">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_23">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_22">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_21">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_20">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_19">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_18">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_17">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_16">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_15">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_14">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_13">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_12">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_11">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_10">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_9">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_8">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_5">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>319</width>
<height>367</height>
</rect>
</property>
<attribute name="label">
<string>家人</string>
</attribute>
<widget class="QPushButton" name="pushButton_24">
<property name="geometry">
<rect>
<x>50</x>
<y>50</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>319</width>
<height>367</height>
</rect>
</property>
<attribute name="label">
<string>朋友</string>
</attribute>
<widget class="QCheckBox" name="checkBox">
<property name="geometry">
<rect>
<x>20</x>
<y>90</y>
<width>98</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_3">
<attribute name="label">
<string>黑名单</string>
</attribute>
<widget class="QToolButton" name="toolButton">
<property name="geometry">
<rect>
<x>40</x>
<y>230</y>
<width>51</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_6">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>百度</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>RadioButton</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>谷歌</string>
</attribute>
<widget class="QPushButton" name="pushButton_25">
<property name="geometry">
<rect>
<x>40</x>
<y>130</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QPushButton" name="btn_scrollArea">
<property name="geometry">
<rect>
<x>360</x>
<y>20</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>scrollArea</string>
</property>
</widget>
<widget class="QPushButton" name="btn_toolBox">
<property name="geometry">
<rect>
<x>360</x>
<y>60</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>toolBox</string>
</property>
</widget>
<widget class="QPushButton" name="btn_tabWidget">
<property name="geometry">
<rect>
<x>360</x>
<y>100</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>tabWidget</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>370</x>
<y>280</y>
<width>83</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="btn_select">
<property name="geometry">
<rect>
<x>360</x>
<y>340</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>select</string>
</property>
</widget>
<widget class="QSpinBox" name="spinBox">
<property name="geometry">
<rect>
<x>350</x>
<y>400</y>
<width>44</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="geometry">
<rect>
<x>430</x>
<y>400</y>
<width>66</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QTimeEdit" name="timeEdit">
<property name="geometry">
<rect>
<x>350</x>
<y>450</y>
<width>118</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QDateEdit" name="dateEdit">
<property name="geometry">
<rect>
<x>350</x>
<y>500</y>
<width>110</width>
<height>25</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
运行结果:
13 自定义控件封装
添加新文件 Qt --> 设计师界面类(.h .cpp .ui)
.ui中 设计QSpinBox和QSlider 两个控件
widget中使用自定义控件,拖拽一个Widget,点击提升为,点击添加,点击提升
实现功能,改变数字,滑动条跟着移动,信号槽监听
提供 getNum 和 setNum 对外接口
勾选全局后,再次添加QWidget,右键“提升为”,会出现子菜单
09_smallWidget
09_smallWidget.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
smallwidget.cpp \
widget.cpp
HEADERS += \
smallwidget.h \
widget.h
FORMS += \
smallwidget.ui \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
smallWidget.h
#ifndef SMALLWIDGET_H
#define SMALLWIDGET_H
#include <QWidget>
namespace Ui {
class SmallWidget;
}
class SmallWidget : public QWidget
{
Q_OBJECT
public:
explicit SmallWidget(QWidget *parent = nullptr);
~SmallWidget();
//设置数字
void setNum(int num);
//获取数字
int getNum();
private:
Ui::SmallWidget *ui;
};
#endif // SMALLWIDGET_H
smallWidget.cpp
#include "smallwidget.h"
#include "ui_smallwidget.h"
SmallWidget::SmallWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::SmallWidget)
{
ui->setupUi(this);
//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);
}
SmallWidget::~SmallWidget()
{
delete ui;
}
//设置数字
void SmallWidget::setNum(int num)
{
ui->spinBox->setValue(num);
}
//获取数字
int SmallWidget::getNum()
{
ui->spinBox->value();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击获取当前值,获取当前控件当前的值
connect(ui->btn_get, &QPushButton::clicked, [=](){
qDebug() << ui->small_widget->getNum();
});
//设置到一半
connect(ui->btn_set, &QPushButton::clicked, [=](){
ui->small_widget->setNum(50);
});
}
Widget::~Widget()
{
delete ui;
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
smallwidget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SmallWidget</class>
<widget class="QWidget" name="SmallWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>286</width>
<height>47</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="spinBox"/>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="SmallWidget" name="small_widget" native="true">
<property name="geometry">
<rect>
<x>30</x>
<y>30</y>
<width>341</width>
<height>51</height>
</rect>
</property>
</widget>
<widget class="SmallWidget" name="widget_2" native="true">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>321</width>
<height>51</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="btn_get">
<property name="geometry">
<rect>
<x>140</x>
<y>200</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>获取当前值</string>
</property>
</widget>
<widget class="QPushButton" name="btn_set">
<property name="geometry">
<rect>
<x>140</x>
<y>280</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>设置到一半</string>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>SmallWidget</class>
<extends>QWidget</extends>
<header location="global">smallwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
14 Qt事件
1 鼠标事件
鼠标进入事件:enterEvent
鼠标离开事件:leaveEvent
鼠标按下事件:mousePressEvent
鼠标释放事件:mouseReleaseEvent
鼠标移动事件:mouseMoveEvent
event->x() ==> x坐标 event->y() ==> y坐标
event->button() 可以判断所有的按键 Qt::LeftButton(鼠标左键),Qt::RightButton(鼠标右键)
event->button() & Qt::LeftButton 判断组合按键 判断move时候的左右键 结合 & 操作符
格式化字符串 QString("%1 %2").arg(111).arg(222)
2 定时器
方式一:
利用事件 void timerEvent(QTimerEvent* evt)
启动定时器 startTimer(1000) 单位是毫秒
timerEvent的返回值是定时器的唯一标识,可以和evt->timerId做比较
方式二:
利用定时器类 QTimer
创建定时器对象 QTimer* timer1 = new QTimer(this)
启动定时器 timer1->startTimer(毫秒)
每隔一定毫秒,发送信号 timeout 进行监听
暂停 timer2->stop()
3 event事件
用途:用于事件的分发
也可以拦截操作,不建议
bool event(QEvent* e)
返回值 如果是true代表用户处理这个事件,不向下分发了
e->type() == 鼠标按下
4 事件过滤器
在程序将事件分发到事件分发器前,可以利用过滤器做拦截
步骤:1、给控件安装事件过滤器;2、重写eventFilter(obj, ev)
10_QtEvent
10_QtEvent.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mylabel.cpp \
widget.cpp
HEADERS += \
mylabel.h \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
myLabel.h
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
class myLabel : public QLabel
{
Q_OBJECT
public:
explicit myLabel(QWidget *parent = nullptr);
//鼠标进入事件
void enterEvent(QEvent* event);
//鼠标离开事件
void leaveEvent(QEvent* event);
//鼠标按下
virtual void mousePressEvent(QMouseEvent* event);
//鼠标释放
virtual void mouseReleaseEvent(QMouseEvent* event);
//鼠标移动
virtual void mouseMoveEvent(QMouseEvent* event);
//通过event事件分发器 拦截 鼠标按下事件
bool event(QEvent *e);
signals:
};
#endif // MYLABEL_H
myLabel.cpp
#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>
myLabel::myLabel(QWidget *parent)
: QLabel{parent}
{
//设置鼠标的追踪状态
setTabletTracking(true);
}
//鼠标进入事件
void myLabel::enterEvent(QEvent* event)
{
qDebug() << "鼠标进入了";
}
//鼠标离开事件
void myLabel::leaveEvent(QEvent* event)
{
qDebug() << "鼠标离开了";
}
//鼠标按下
void myLabel::mousePressEvent(QMouseEvent* event)
{
//当鼠标左键按下 提示信息
if (event->button() == Qt::LeftButton){
QString str = QString("鼠标按下了 x = %1 y = %2 globalX = %3 globalY = %4").arg(event->x()).arg(event->y()).arg(event->globalX()).arg(event->globalY());
qDebug() << str;
}
}
//鼠标释放
void myLabel::mouseReleaseEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton)
{
QString str = QString("鼠标释放了 x = %1 y = %2 globalX = %3 globalY = %4").arg(event->x()).arg(event->y()).arg(event->globalX()).arg(event->globalY());
qDebug() << str;
}
}
//鼠标移动
void myLabel::mouseMoveEvent(QMouseEvent* event)
{
//鼠标移动是连续,只有瞬间的才能判断鼠标左键;
//可以使用 &
//if (event->button() == Qt::LeftButton)
if (event->button() & Qt::LeftButton)
{
QString str = QString("鼠标移动了 x = %1 y = %2 globalX = %3 globalY = %4").arg(event->x()).arg(event->y()).arg(event->globalX()).arg(event->globalY());
qDebug() << str;
}
}
//通过event事件分发器 拦截 鼠标按下事件
bool myLabel::event(QEvent *e)
{
//如果是鼠标按下,在event事件分发中做拦截操作
if (e->type() == QEvent::MouseButtonPress)
{
QMouseEvent* ev = static_cast<QMouseEvent*>(e);
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);
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//重写定时器事件
void timerEvent(QTimerEvent *event);
int id1; //定时器1的唯一标识
int id2; //定时器2的唯一标识
//重写事件过滤器的事件
bool eventFilter(QObject *watched, QEvent *event);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTimer> //定时器的类
#include <QMouseEvent>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//启动定时器
id1 =startTimer(1000);//参数1:间隔(单位是毫秒)
id2 = startTimer(2000);
//定时器第二种方式
QTimer* timer1 = new QTimer(this);
//启动定时器
timer1->start(500);
connect(timer1, &QTimer::timeout, [=](){
//label4 每隔0.5秒+1
static int num = 1;
ui->label_4->setText(QString::number(num++));
});
//点击暂停按钮,实现停止定时器
connect(ui->btn, &QPushButton::clicked, [=](){
timer1->stop();
});
//给label1 安装事件过滤器
//步骤1 安装事件过滤器
ui->label->installEventFilter(this);
}
Widget::~Widget()
{
delete ui;
}
//重写定时器事件
void Widget::timerEvent(QTimerEvent *event)
{
if (event->timerId() == id1)
{
//label2 每隔1秒+1
static int num = 1;
ui->label_2->setText(QString::number(num++));
} else if (event->timerId() == id2){
//label3 每隔2秒+1
static int num = 1;
ui->label_3->setText(QString::number(num++));
}
}
//步骤2 重写eventFilter事件
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->label)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* ev = static_cast<QMouseEvent*>(event);
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, event);
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="myLabel" name="label">
<property name="geometry">
<rect>
<x>60</x>
<y>40</y>
<width>271</width>
<height>51</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::Shape::Box</enum>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>60</x>
<y>120</y>
<width>291</width>
<height>81</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::Shape::Panel</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>60</x>
<y>220</y>
<width>281</width>
<height>51</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::Shape::WinPanel</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>60</x>
<y>310</y>
<width>281</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::Shape::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Sunken</enum>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QPushButton" name="btn">
<property name="geometry">
<rect>
<x>360</x>
<y>320</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>暂停</string>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>myLabel</class>
<extends>QLabel</extends>
<header location="global">mylabel.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
15 QPainter绘图
绘图事件 void paintEvent(QPaintEvent* evt)
声明一个画家对象 QPainter painter(this); //this指定绘画设备
画线、画圆、画椭圆、画文字
设置画笔 QPen 设置画笔宽度、风格
设置画刷 QBrush 设置画刷 风格
QPainter高级设置:
抗锯齿能力 效率低 painter.setRenderHint(QPainter::Antialiasing);
对画家进行移动 painter.translate(100, 0);
保存画家状态 painter.save();
还原画家保存状态 painter.restore();
如果想手动调用绘图事件 利用update
利用画家画图片 painter.drawPixmap(x,y,QPixmap(":/image/image1.jpg"))
11_QPainter
11_QPainter.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
res.qrc
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void paintEvent(QPaintEvent* evt);
private:
Ui::Widget *ui;
int posX = 0;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter> //画家类
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击移动按钮 图片向右移动
connect(ui->pushButton, &QPushButton::clicked, [=]{
posX +=20;
//如果要手动调用绘图事件,用update更新
update();
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent* evt)
{
/*
///普通设置///
//实例化画家对象 this指定的是绘画的设备
QPainter painter(this);
//画线
painter.drawLine(QPoint(0, 0), QPoint(100, 100));
//画圆
painter.drawEllipse(QPoint(100, 100), 50, 50);
//设置画笔
QPen pen(QColor(255, 0, 0));
//设置画笔宽度
pen.setWidth(10);
//设置画笔风格
pen.setStyle(Qt::DotLine);
//让画家 使用这个笔
painter.setPen(pen);
//画椭圆
painter.drawEllipse(QPoint(100, 100), 100, 50);
//设置画刷——填充封闭图像内部
QBrush brush(QColor(Qt::green));
//设置画刷风格
brush.setStyle(Qt::Dense2Pattern);
//让画家使用画刷
painter.setBrush(brush);
//画矩形
painter.drawRect(QRect(300, 100, 100, 50));
//画文字
painter.drawText(QRect(10, 200, 100, 50), "好好学习");
*/
/*
///高级设置///
QPainter painter(this);
painter.drawEllipse(QPoint(100, 50), 50, 50);
//设置 抗锯齿能力 效率低
painter.setRenderHint(QPainter::Antialiasing);
painter.drawEllipse(QPoint(200, 50), 50, 50);
//画矩形
painter.drawRect(QRect(120, 150, 50, 50));
//移动画家 坐标轴移动到(100,0)
painter.translate(100, 0);
//保存画家状态
painter.save();
painter.drawRect(QRect(120, 150, 50, 50));
//移动画家 坐标轴移动到(200,0)
painter.translate(100, 0);
//还原画家保存状态
painter.restore();
painter.drawRect(QRect(120, 150, 50, 50));
*/
利用画家 画资源图片//
QPainter painter(this);
//如果超出屏幕 从0开始
if (posX > this->width())
{
posX = 0;
}
painter.drawPixmap(posX, 20, QPixmap(":/Image/image1.jpg"));
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>481</width>
<height>444</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>370</x>
<y>380</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>移动</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
16 QPaintDevice 绘图设备
QPixmap QImage QBttmap(黑白色) QPicture QWidget
QPixmap 对不同平台做了显示的优化
QPixmap pix(300, 300)
背景默认是黑色,设置背景颜色 pix.fill(Qt::green)
利用画家 往pix上画画 QPainter painter(&pix)
保存 pix.save("路径")
QImage 可以对像素进行访问
使用和QPixmap差不多 QImage img(300, 300, QImage::Format_RGB32)
其他流程和QPixmap一样
可以对像素进行修改img.setPixel(i, j, value),设置像素QRgb value = qRgb(255, 0, 0)
QPicture 记录和重现绘图指令
QPicture pic;
开始绘画 painter.begin(&pic);
保存 pic.save("任意后缀名");
绘画结束 painter.end();
重现QPicture的绘图指令 painter.drawPicture(0, 0, pic);
12_QtPaintDevice
12_QtPaintDevice.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
res.qrc
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//绘图事件
void paintEvent(QPaintEvent* evt);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QPainter>
#include <QImage>
#include <QPicture>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
/*
//Pixmap绘图设备 专门为平台做了显示的优化
QPixmap pix(300, 300);
//填充颜色
pix.fill(Qt::white);
//声明画家
QPainter painter(&pix);
painter.setPen(QPen(Qt::green));
painter.drawEllipse(QPoint(150, 150), 100, 100);
//保存
pix.save("E:\\pix.png");
*/
/*
//QImage 绘图设备 可以对像素进行访问
QImage img(300, 300, QImage::Format_RGB32);
img.fill(Qt::white);
QPainter painter(&img);
painter.setPen(QPen(Qt::green));
painter.drawEllipse(QPoint(150, 150), 100, 100);
//保存
img.save("E:\\img.png");
*/
//QPicture 绘图设备 可以记录和重现绘图指令
QPicture pic;
QPainter painter;
//开始绘画
painter.begin(&pic);
painter.setPen(QPen(Qt::red));
painter.drawEllipse(QPoint(150, 150), 100, 100);
//绘画结束
painter.end();
//保存
pic.save("E:\\pic.zt");
}
Widget::~Widget()
{
delete ui;
}
//绘图事件
void Widget::paintEvent(QPaintEvent* evt)
{
/*
//利用QImage 对像素进行修改
QImage img;
img.load(":/Image/image1.jpg");
QPainter painter(this);
//修改像素点
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);
*/
//重现QPicture的绘图指令
QPicture pic;
pic.load("E://pic.zt");
QPainter painter(this);
painter.drawPicture(0, 0, pic);
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
17 QFile 对文件进行读写操作
QFile 进行读写操作:QFile file(path 文件路径)
读:
file.open(打开方式) QIODevice::ReadOnly
全部读取 file.readAll();按行读取 file.readLine();判断是否读到文件尾 file.atEnd()
默认支持编码格式 utf-8
利用编码格式类 指定格式QTextCodec(若QTextCodec 编译失败,在pro文件中添加greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat)
QTextCodec* codec = QTextCodec::codecForName("gbk");
ui->textEdit->setText(codec->toUnicode(array));
文件对象关闭 file.close();
写:
file.open(QIODevice::Append); //用追加的方式进行写
file.write(内容)
file.close() 关闭
读取文件信息:
大小:info.size()
后缀名:info.suffix()
文件名称:info.fileName()
文件路径:info.path()
创建日期:info.birthTime().toString("yyyy/MM/dd hh:mm:ss")
最后修改日期:info.lastModified().toString("yyyy-MM-dd hh:mm:ss");
13_Qt_QFile
13_Qt_QFile.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QFile>
#include <QTextCodec>
#include <QDebug>
#include <QDateTime>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击选取文件,弹出文件对话框
connect(ui->pushButton, &QPushButton::clicked, [=](){
QString path = QFileDialog::getOpenFileName(this, "打开文件", "D:\\Desktop");
//将路径放入到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();
//将读取到的数据 放到textEdit中
//ui->textEdit->setText(array);
//ui->textEdit->setText(codec->toUnicode(array));
//按行读
QByteArray array;
while (!file.atEnd())
{
array += file.readLine();
}
ui->textEdit->setText(array);
//对文件对象进行关闭
file.close();
//进行写文件
file.open(QIODevice::Append); //用追加的方式进行写
file.write("aaaaaaaaaaa");
file.close();
//QFileInfo 文件信息类
QFileInfo info(path);
qDebug() << "大小:" << info.size()
<< " 后缀名:" << info.suffix()
<< " 文件名称:" << info.fileName()
<< " 文件路径:" << info.path()
<< " 创建日期:" << info.birthTime().toString("yyyy/MM/dd hh:mm:ss")
<< " 最后修改日期:" << info.lastModified().toString("yyyy-MM-dd hh:mm:ss");
});
}
Widget::~Widget()
{
delete ui;
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>538</width>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>选取文件</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
18 案例-翻金币
打包发布
新建文件夹,把CoinFlip.exe拷贝到文件夹下
打开cmd
CoinFlip
CoinFlip.pro
QT += core gui
QT += multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
chooselevelscene.cpp \
dataconfig.cpp \
main.cpp \
mainscene.cpp \
mycoin.cpp \
mypushbutton.cpp \
playscene.cpp
HEADERS += \
chooselevelscene.h \
dataconfig.h \
mainscene.h \
mycoin.h \
mypushbutton.h \
playscene.h
FORMS += \
mainscene.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
res.qrc
chooselevelscene.h
#ifndef CHOOSELEVELSCENE_H
#define CHOOSELEVELSCENE_H
#include <QMainWindow>
#include "playscene.h"
class ChooseLevelScene : public QMainWindow
{
Q_OBJECT
public:
explicit ChooseLevelScene(QWidget *parent = nullptr);
//重写绘图事件
void paintEvent(QPaintEvent *event);
//游戏场景对象指针
PlayScene* play = NULL;
signals:
//写一个自定义信号,告诉主场景 点击了返回
//自定义信号只需要声明,不需要实现
void chooseSceneBack();
};
#endif // CHOOSELEVELSCENE_H
chooselevelscene.cpp
#include "chooselevelscene.h"
#include <QPixmap>
#include <QMenuBar>
#include <QPainter>
#include <QPixmap>
#include "mypushbutton.h"
#include <QDebug>
#include <QTimer>
#include <QLabel>
#include <QSoundEffect>
ChooseLevelScene::ChooseLevelScene(QWidget *parent)
: QMainWindow{parent}
{
//配置选择关卡场景
this->setFixedSize(320, 588);
//设置图标
this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
//设置标题
this->setWindowTitle("选择关卡场景");
//创建菜单栏
QMenuBar* bar = menuBar();
this->setMenuBar(bar);
//创建开始菜单
QMenu* startMenu = bar->addMenu("开始");
//创建退出 菜单项
QAction* quitAction = startMenu->addAction("退出");
//点击退出 实现退出游戏
connect(quitAction, &QAction::triggered, [=](){
this->close();
});
//选择关卡的音效
QSoundEffect* chooseSound = new QSoundEffect();
chooseSound->setSource(QUrl::fromLocalFile(":/res/TapButtonSound.wav"));
//返回按钮的音效
QSoundEffect* backSound = new QSoundEffect();
backSound->setSource(QUrl::fromLocalFile(":/res/BackButtonSound.wav"));
//返回按钮
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() << "点击了返回按钮";
//播放返回按钮的音效
backSound->play();
//延时返回
QTimer::singleShot(500, this, [=](){
//告诉主场景,我返回了,主场景监听ChooseLevelScene的返回按钮
emit this->chooseSceneBack();
});
});
//创建选择关卡的按钮
for (int i = 0; i < 20; i++)
{
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;
//播放选择关卡的音效
chooseSound->play();
play = new PlayScene(i+1); //创建游戏场景
//设置游戏场景的初始位置
play->setGeometry(this->geometry());
//进入到游戏场景
this->hide(); //将选关场景隐藏掉
play->show(); //显示游戏场景
connect(play, &PlayScene::chooseSceneBack, [=](){
this->setGeometry(play->geometry());
this->show();
delete play;
play = NULL;
});
});
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);
}
}
//重写绘图事件
void ChooseLevelScene::paintEvent(QPaintEvent *event)
{
//加载背景
QPainter painter(this);
QPixmap pix;
pix.load(":/res/OtherSceneBg.png");
painter.drawPixmap(0, 0, this->width(), this->height(), pix);
//画背景上图标
pix.load(":/res/Title.png");
painter.drawPixmap((this->width()-pix.width())*0.5, 30, pix.width(), pix.height(), pix);
}
dataconfig.h
#ifndef DATACONFIG_H
#define DATACONFIG_H
#include <QObject>
#include <QMap>
#include <QVector>
class dataConfig : public QObject
{
Q_OBJECT
public:
explicit dataConfig(QObject *parent = 0);
public:
QMap<int, QVector< QVector<int> > >mData;
signals:
public slots:
};
#endif // DATACONFIG_H
dataconfig.cpp
#include "dataconfig.h"
#include <QDebug>
dataConfig::dataConfig(QObject *parent) : QObject(parent)
{
int array1[4][4] = {{1, 1, 1, 1},
{1, 1, 0, 1},
{1, 0, 0, 0},
{1, 1, 0, 1} } ;
QVector< QVector<int>> v;
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array1[i][j]);
}
v.push_back(v1);
}
mData.insert(1,v);
int array2[4][4] = { {1, 0, 1, 1},
{0, 0, 1, 1},
{1, 1, 0, 0},
{1, 1, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array2[i][j]);
}
v.push_back(v1);
}
mData.insert(2,v);
int array3[4][4] = { {0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array3[i][j]);
}
v.push_back(v1);
}
mData.insert(3,v);
int array4[4][4] = { {0, 1, 1, 1},
{1, 0, 0, 1},
{1, 0, 1, 1},
{1, 1, 1, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array4[i][j]);
}
v.push_back(v1);
}
mData.insert(4,v);
int array5[4][4] = { {1, 0, 0, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{1, 0, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array5[i][j]);
}
v.push_back(v1);
}
mData.insert(5,v);
int array6[4][4] = { {1, 0, 0, 1},
{0, 1, 1, 0},
{0, 1, 1, 0},
{1, 0, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array6[i][j]);
}
v.push_back(v1);
}
mData.insert(6,v);
int array7[4][4] = { {0, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 0, 1},
{1, 1, 1, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array7[i][j]);
}
v.push_back(v1);
}
mData.insert(7,v);
int array8[4][4] = { {0, 1, 0, 1},
{1, 0, 0, 0},
{0, 0, 0, 1},
{1, 0, 1, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array8[i][j]);
}
v.push_back(v1);
}
mData.insert(8,v);
int array9[4][4] = { {1, 0, 1, 0},
{1, 0, 1, 0},
{0, 0, 1, 0},
{1, 0, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array9[i][j]);
}
v.push_back(v1);
}
mData.insert(9,v);
int array10[4][4] = { {1, 0, 1, 1},
{1, 1, 0, 0},
{0, 0, 1, 1},
{1, 1, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array10[i][j]);
}
v.push_back(v1);
}
mData.insert(10,v);
int array11[4][4] = { {0, 1, 1, 0},
{1, 0, 0, 1},
{1, 0, 0, 1},
{0, 1, 1, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array11[i][j]);
}
v.push_back(v1);
}
mData.insert(11,v);
int array12[4][4] = { {0, 1, 1, 0},
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array12[i][j]);
}
v.push_back(v1);
}
mData.insert(12,v);
int array13[4][4] = { {0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 1, 1, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array13[i][j]);
}
v.push_back(v1);
}
mData.insert(13,v);
int array14[4][4] = { {1, 0, 1, 1},
{0, 1, 0, 1},
{1, 0, 1, 0},
{1, 1, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array14[i][j]);
}
v.push_back(v1);
}
mData.insert(14,v);
int array15[4][4] = { {0, 1, 0, 1},
{1, 0, 0, 0},
{1, 0, 0, 0},
{0, 1, 0, 1}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array15[i][j]);
}
v.push_back(v1);
}
mData.insert(15,v);
int array16[4][4] = { {0, 1, 1, 0},
{1, 1, 1, 1},
{1, 1, 1, 1},
{0, 1, 1, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array16[i][j]);
}
v.push_back(v1);
}
mData.insert(16,v);
int array17[4][4] = { {0, 1, 1, 1},
{0, 1, 0, 0},
{0, 0, 1, 0},
{1, 1, 1, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array17[i][j]);
}
v.push_back(v1);
}
mData.insert(17,v);
int array18[4][4] = { {0, 0, 0, 1},
{0, 0, 1, 0},
{0, 1, 0, 0},
{1, 0, 0, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array18[i][j]);
}
v.push_back(v1);
}
mData.insert(18,v);
int array19[4][4] = { {0, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array19[i][j]);
}
v.push_back(v1);
}
mData.insert(19,v);
int array20[4][4] = { {0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}} ;
v.clear();
for(int i = 0 ; i < 4;i++)
{
QVector<int>v1;
for(int j = 0 ; j < 4;j++)
{
v1.push_back(array20[i][j]);
}
v.push_back(v1);
}
mData.insert(20,v);
//测试数据
// for( QMap<int, QVector< QVector<int> > >::iterator it = mData.begin();it != mData.end();it++ )
// {
// for(QVector< QVector<int> >::iterator it2 = (*it).begin(); it2!= (*it).end();it2++)
// {
// for(QVector<int>::iterator it3 = (*it2).begin(); it3 != (*it2).end(); it3++ )
// {
// qDebug() << *it3 ;
// }
// }
// qDebug() << endl;
// }
}
mainscene.h
#ifndef MAINSCENE_H
#define MAINSCENE_H
#include <QMainWindow>
#include "chooselevelscene.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainScene;
}
QT_END_NAMESPACE
class MainScene : public QMainWindow
{
Q_OBJECT
public:
MainScene(QWidget *parent = nullptr);
~MainScene();
//重写paintEvent事件 画背景图片
void paintEvent(QPaintEvent* evt);
ChooseLevelScene* chooseScene = NULL;
private:
Ui::MainScene *ui;
};
#endif // MAINSCENE_H
mainscene.cpp
#include "mainscene.h"
#include "ui_mainscene.h"
#include <QPainter>
#include <QPixmap>
#include "mypushbutton.h"
#include <QDebug>
#include <QTimer>
#include <QSoundEffect> //多媒体模块下 的音效头文件
MainScene::MainScene(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainScene)
{
ui->setupUi(this);
//配置主场景
//设置固定大小
this->setFixedSize(320, 588);
//设置图标
this->setWindowIcon(QIcon(":/res/Coin0001.png"));
//设置标题
this->setWindowTitle("翻金币主场景");
//退出按钮实现
connect(ui->actionQuit, &QAction::triggered, [=](){
this->close();
});
//准备开始按钮的音效
QSoundEffect* startSound = new QSoundEffect();
startSound->setSource(QUrl::fromLocalFile(":/res/TapButtonSound.wav"));
//设置循环次数(-1代表无限循环)
//startSound->setLoopCount(10);
//开始按钮
MyPushButton* startBtn = new MyPushButton(":/res/MenuSceneStartButton.png");
startBtn->setParent(this);
startBtn->move(this->width()*0.5 - startBtn->width()*0.5, this->height()*0.7);
//实例化选择关卡场景
chooseScene = new ChooseLevelScene;
//监听选择关卡的返回按钮的信号
connect(chooseScene, &ChooseLevelScene::chooseSceneBack, [=](){
this->setGeometry(chooseScene->geometry());
//隐藏选择场景
chooseScene->hide();
//重新显示主场景
this->show();
});
connect(startBtn, &MyPushButton::clicked, [=](){
qDebug() << "点击了开始";
//播放开始的音效
startSound->play();
//做弹起特效
startBtn->zoom1();
startBtn->zoom2();
//延时进入到选择关卡场景中
QTimer::singleShot(500, this, [=](){
//设置chooseScene场景的位置
chooseScene->setGeometry(this->geometry());
//自身隐藏
this->hide();
//显示选择关卡场景
chooseScene->show();
});
});
}
MainScene::~MainScene()
{
delete ui;
}
//重写paintEvent事件 画背景图片
void MainScene::paintEvent(QPaintEvent* evt)
{
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);
}
mycoin.h
#ifndef MYCOIN_H
#define MYCOIN_H
#include <QPushButton>
#include <QTimer>
class MyCoin : public QPushButton
{
Q_OBJECT
public:
//explicit MyCoin(QWidget *parent = nullptr);
//参数代表传入金币路径,还是银币路径
MyCoin(QString btnImg);
//金币的属性
int posX; //x坐标位置
int posY; //y坐标位置
bool flag; //正反标识
//改变标志的方法
void changeFlag();
QTimer* timer1; //正面翻反面的定时器
QTimer* timer2; //反面翻正面的定时器
int min = 1;
int max = 8;
//执行动画 标志
bool isAnimation = false;
//重写 按下
void mousePressEvent(QMouseEvent *e);
//是否胜利的标志
bool isWin;
signals:
};
#endif // MYCOIN_H
mycoin.cpp
#include "mycoin.h"
#include <QPixmap>
#include <QDebug>
// MyCoin::MyCoin(QWidget *parent)
// : QPushButton{parent}
// {}
MyCoin::MyCoin(QString btnImg)
{
QPixmap pix;
bool ret = pix.load(btnImg);
if (!ret)
{
qDebug() << QString("图片%1加载失败").arg(btnImg);
return;
}
this->setFixedSize(pix.width(), pix.height());
this->setStyleSheet("QPushButton{border:0px;}");
this->setIcon(pix);
this->setIconSize(QSize(pix.width(), pix.height()));
//初始化定时器对象
timer1 = new QTimer(this);
timer2 = new QTimer(this);
//监听正面翻反面的信号,并且翻转金币
connect(timer1, &QTimer::timeout, [=](){
QPixmap pix;
pix.load(QString(":/res/Coin000%1.png").arg(this->min++));
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;
pix.load(QString(":/res/Coin000%1.png").arg(this->max--));
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->max < this->min)
{
this->max = 8;
timer2->stop();
isAnimation = false;
}
});
}
//改变正反面标志的方法
void MyCoin::changeFlag()
{
//如果是正面 翻成反面
if (this->flag)
{
//开始正面翻反面的定时器
timer1->start(30);
isAnimation = true; //开始做动画
this->flag = false;
}
//反面翻正面
else
{
timer2->start(30);
isAnimation = true; //开始做动画
this->flag = true;
}
}
void MyCoin::mousePressEvent(QMouseEvent *e)
{
if (this->isAnimation || this->isWin)
{
return;
}
QPushButton::mousePressEvent(e);
}
mypushbutton.h
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QPushButton>
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
//explicit MyPushButton(QWidget *parent = nullptr);
//构造函数 参数1:正常显示的图片路径;参数2:按下后显示的图片路径
MyPushButton(QString normalImg, QString pressImg = "");
//成员属性
//保存用户传入的默认显示路径
QString normalImgPath;
//按下后显示的图片路径
QString pressImgPath;
//弹跳特效
void zoom1(); //向下跳
void zoom2(); //向上跳
//重写按钮 按下 和 释放 事件
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
signals:
};
#endif // MYPUSHBUTTON_H
mypushbutton.cpp
#include "mypushbutton.h"
#include <QPixmap>
#include <QPainter>
#include <QDebug>
#include <QSize>
#include <QPropertyAnimation>
// MyPushButton::MyPushButton(QWidget *parent)
// : QPushButton{parent}
// {}
MyPushButton::MyPushButton(QString normalImg, QString pressImg)
{
this->normalImgPath = normalImg;
this->pressImgPath = pressImg;
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()));
}
//弹跳特效 向下跳
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();
}
//重写按钮 按下 和 释放 事件
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->pressImgPath != "") //传入的按下图片不为空:说明需要有按下状态,切换成初始图片
{
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);
}
playscene.h
#ifndef PLAYSCENE_H
#define PLAYSCENE_H
#include <QMainWindow>
#include "mycoin.h"
class PlayScene : public QMainWindow
{
Q_OBJECT
public:
//explicit PlayScene(QWidget *parent = nullptr);
PlayScene(int levelNum);
//内部成员函数 记录所选的关卡
int levelIndex;
//重新paintEvent事件
void paintEvent(QPaintEvent *event);
int gameArray[4][4]; //二维数组,维护每个关卡的具体数据
MyCoin* coinBtn[4][4];
//是否胜利的标志
bool isWin;
signals:
void chooseSceneBack();
};
#endif // PLAYSCENE_H
playscene.cpp
#include "playscene.h"
#include <QDebug>
#include <QPixmap>
#include <QMenuBar>
#include <QMenu>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
#include "mypushbutton.h"
#include <QLabel>
#include <QFont>
#include "mycoin.h"
#include "dataconfig.h"
#include <QPropertyAnimation>
#include <QSoundEffect>
// PlayScene::PlayScene(QWidget *parent)
// : QMainWindow{parent}
// {}
PlayScene::PlayScene(int levelNum)
{
qDebug() << QString("进入了第 %1 关").arg(levelNum);
this->levelIndex = levelNum;
//初始化游戏场景
//设置固定大小
this->setFixedSize(320, 588);
//设置图标
this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
//设置标题
this->setWindowTitle("翻金币场景");
//创建菜单栏
QMenuBar* bar = menuBar();
this->setMenuBar(bar);
//创建开始菜单
QMenu* startMenu = bar->addMenu("开始");
//创建退出 菜单项
QAction* quitAction = startMenu->addAction("退出");
//点击退出 实现退出游戏
connect(quitAction, &QAction::triggered, [=](){
this->close();
});
//翻金币的音效
QSoundEffect* flipSound = new QSoundEffect();
flipSound->setSource(QUrl::fromLocalFile(":/res/CoinFlipSound.wav"));
//胜利的音效
QSoundEffect* winSound = new QSoundEffect();
winSound->setSource(QUrl::fromLocalFile(":/res/LevelWinSound.wav"));
//返回按钮的音效
QSoundEffect* backSound = new QSoundEffect();
backSound->setSource(QUrl::fromLocalFile(":/res/BackButtonSound.wav"));
//返回按钮
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() << "翻金币场景中:点击了返回按钮";
//播放返回按钮的音效
backSound->play();
//延时返回
QTimer::singleShot(500, this, [=](){
//告诉主场景,我返回了,主场景监听ChooseLevelScene的返回按钮
emit this->chooseSceneBack();
});
});
//显示当前关卡号
QLabel* label = new QLabel;
label->setParent(this);
QFont font;
font.setFamily("华文新魏");
font.setPointSize(20);
//将字体设置到标签中
label->setFont(font);
label->setText(QString("Leavel: %1").arg(this->levelIndex));
label->setGeometry(QRect(30, this->height()-50, 120, 50));
dataConfig config;
//初始化每个关卡的二维数组
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
this->gameArray[i][j] = config.mData[this->levelIndex][i][j];
}
}
//胜利图片显示
QLabel* winLabel = new QLabel;
winLabel->setParent(this);
QPixmap tmpPix;
tmpPix.load(":/res/LevelCompletedDialogBg.png");
winLabel->setGeometry(0, 0, tmpPix.width(), tmpPix.height());
winLabel->setPixmap(tmpPix);
winLabel->move((this->width()-tmpPix.width())*0.5, -tmpPix.height());
//显示金币背景图片
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
//绘制背景图片
QPixmap pix = QPixmap(":/res/BoardNode.png");
QLabel* label = new QLabel;
label->setParent(this);
label->setGeometry(0, 0, pix.width(), pix.height());
label->setPixmap(pix);
label->move(57+i*50, 200+j*50);
//创建金币
QString str;
if (this->gameArray[i][j] == 1)
{
//显示金币
str = ":/res/Coin0001.png";
}
else
{
str = ":/res/Coin0008.png";
}
MyCoin* coin = new MyCoin(str);
coin->setParent(this);
coin->move(59+i*50, 204+j*50);
//给金币属性赋值
coin->posX = i;
coin->posY = j;
coin->flag = this->gameArray[i][j]; //1:正面,0:反面
//将金币放入到 金币的二位数组中 以便以后的维护
coinBtn[i][j] = coin;
//点击金币 进行翻转
connect(coin, &MyCoin::clicked, [=](){
//播放翻金币的音效
flipSound->play();
//点击按钮 将所有的金币都先禁用
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
this->coinBtn[i][j]->isWin = true;
}
}
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 <= 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;
}
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;
}
//翻完周围金币后,将所有金币解开禁用
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
this->coinBtn[i][j]->isWin = false;
}
}
//判断是否胜利
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)
{
//添加胜利的音效
winSound->play();
qDebug() << "游戏胜利";
//将所有按钮的胜利标志改为true
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
coinBtn[i][j]->isWin = true;
}
}
//将胜利的图片移动下来
QPropertyAnimation* animation = new QPropertyAnimation(winLabel, "geometry");
//设置时间间隔
animation->setDuration(1000);
//设置开始位置
animation->setStartValue(QRect(winLabel->x(), winLabel->y(), winLabel->width(), winLabel->height()));
//设置结束位置
animation->setEndValue(QRect(winLabel->x(), winLabel->y()+114, winLabel->width(), winLabel->height()));
//设置缓和曲线
animation->setEasingCurve(QEasingCurve::OutBounce);
//执行动画
animation->start();
}
});
});
}
}
}
void PlayScene::paintEvent(QPaintEvent *event)
{
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.width(), pix.height(), pix);
}
main.cpp
#include "mainscene.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainScene w;
w.show();
return a.exec();
}
mainscene.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainScene</class>
<widget class="QMainWindow" name="MainScene">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainScene</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>开始</string>
</property>
<addaction name="actionQuit"/>
</widget>
<addaction name="menu"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionQuit">
<property name="text">
<string>退出</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
19 代码
通过网盘分享的文件:Qt.zip
链接: https://pan.baidu.com/s/1WdHz54L7LlpHU1I3jOaieg?pwd=gd8w 提取码: gd8w