@Qt学习与开发
“ 第一次写博客,尝试将自己的思路记录下来。”
一个挺巧妙的机会能接触到Qt,Qt是一个构建人机交互界面的很好的工具,首先我们需要配置好Qt环境。Qt下载链接link,一般选择5.9以上版本,然后安装的时候有两种编译方式,直接选择对应64位的MSVC即可。进入之后可以通过运行一个应用实例查看安装是否正确。
首先创建一个MainWidget应用程序实例,生成Form的ui文件不勾选(界面化编程),后续的语言和工具包Kit选取自己默认的系统版本64位,选定生成文件的路径(尽量不适用中文名)。
我们先考虑整个开发框架的思维导图:
代码和资源文件的基本部署流程:
在项目的现有初始化资源文件中,现有的文件中那些坐标、鼠标响应和计时器等文件是资源文件中的,然后我们主要了解基础的开发思路和方法,结合开发导图依次添加视图和场景代码:
// 将gameView创建并添加到MainWidget文件
QGraphicsView *gameView = new QGraphicsView(this); //给指针变量申请一个内存指针
QGraphicsScene *gameScene = new QGraphicsScene;
gameView->setScene(gameScene); //在对应的类中查看有该方法设置scene
//ImageManager文件中load函数载入背景图片
QGraphicsPixmapItem *backgroundItem = new QGraphicsPixmapItem(gImageCache->load("interface/background1.jpg"));
gameScene->addItem(backgroundItem); //添加进场景
//需要添加ImageManager和GraphicsItem头文件(声明错误)
可以右键QGraphicsView进入上下文相关帮助查看用法,其中Header--头文件需要添加 和 qmake--在.pro文件中添加配置
InitImageManager(); //调用初始化函数方法
//MainWidget cpp文件中
gameView->setGeometry(0,0,800,600); //设置窗口大小
//gameview头文件中的构造函数声明
public:
//形式需要修改,涉及一个父类,模仿mainwidget文件中的构造函数
GameView(QWidget *parent = nullptr);
//gameview.cpp文件中实现代码,形参和初始化列表
GameView::GameView(QWidget *parent):QGraphicsView(parent){
}
//gamescene头文件中声明一个Item变量,需添加对应Item头文件
QGraphicsPixmapItem *backgroundItem;
class GameView; //利用类声明,可以不用包含很多头文件
class GameScene; //代码重构!!!
//头文件包含头文件的方式会导致拉出头文件解释
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr); //构造和析构函数
~MainWidget();
GameView *gameView;
GameScene *gameScene;
};
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent),gameView(new GameView(this)),gameScene(new GameScene)
{
....//视图和场景实现代码
}
GameView::GameView(QWidget *parent):QGraphicsView(parent)
{
setGeometry(0,0,800,600); //设置窗口大小;利用两个变量来设置
}
GameScene::GameScene():backgroundItem(new QGraphicsPixmapItem(gImageCache->load("interface/background1.jpg")))
{
addItem(backgroundItem); //添加进场景
}
GameView::GameView(QWidget *parent):QGraphicsView(parent),gameScene(new GameScene)
{
setScene(gameScene); //设置场景得放在前面
}
整个场景的设置,综合来说就是界面框架、视图和场景以及元素之间的一个关系,首先是视图类和场景类的自定义声明,以及将原本在界面中实现的视图和场景以及元素(背景图片)设置的代码转换到自身的类定义中;其次,GameView和GameScene就类似于GameScene和GraphicsItem之间的关系,所以设置场景SetScene函数方法就可以添加到GameView中,只需要添加相应的GameScene的初始化列表,类似于背景图的设置addItem函数方法添加到GameScene中以及初始化列表中的声明变量backgroundItem的初始化。
除草机作为一个场景元素,自然是背景图一样,添加到GameScene的实现中。同理定义场景元素GraphicsPixmapItem,其定义方式同背景图,利用图片的存储路径作为形参进行声明定义。
GameScene::GameScene():backgroundItem(new QGraphicsPixmapItem(gImageCache->load("interface/background1.jpg")))
{
addItem(backgroundItem); //添加进场景
//方法①:笨方法,直接如此声明定义5个场景元素进行初始化---缺点是代码可读性和重用性差
QGraphicsPixmapItem *lawncleaner1 = new QGraphicsPixmapItem(gImageCache->load("interface/LawnCleaner.png"));
lawncleaner1->setPos(180,100); //如果有父类,那么就是在父坐标系中;如果没有就是scene坐标系
lawncleaner1->setParentItem(backgroundItem); //设置父类元素,隐式地将此图形项添加到父级的场景中
//方法②:利用坐标系函数,根据背景图中的行和列格子自己寻找对应的位置
#include "Coordinate.h"
Coordinate cor; //生成一个坐标系,告诉你行列的存在,一格一格
for(int i=0;i<5;++i){
QGraphicsPixmapItem *lawncleaner = new QGraphicsPixmapItem(gImageCache->load("interface/LawnCleaner.png"));
lawncleaner->setPos(cor.getX(1),cor.getY(i)); //对应的列--X 和行--Y
lawncleaner->setParentItem(backgroundItem);
}//这样定义不太好:因为除草机需要触发机器开走的效果
其中不同之处在于除草机是在背景图之上呈现的元素,所以给他添加一个父类元素setParentItem,如此可以保证元素的显示不会因为代码顺序问题出现混乱。