【Qt项目专栏】贪吃蛇小游戏1.0

2024-06-17 17:28

本文主要是介绍【Qt项目专栏】贪吃蛇小游戏1.0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


  • 博客主页:Duck Bro 博客主页
  • 系列专栏:Qt 专栏
  • 关注博主,后期持续更新系列文章
  • 如果有错误感谢请大家批评指出,及时修改
  • 感谢大家点赞👍收藏⭐评论✍

贪吃蛇小游戏1.0

项目编号:01

文章目录

  • 贪吃蛇小游戏1.0
    • 一、项目介绍及演示
      • 1. 项目介绍
      • 2. 项目演示
      • 3. 窗口介绍
        • 3.1 游戏大厅窗口
        • 3.2 游戏关卡选择窗口
        • 3.3 游戏房间窗口
    • 二、创建项目及资源配置
      • 1. 创建项目(QWidget)
      • 2. 资源配置(图片声音素材)
    • 三、项目实现
      • 1. 游戏大厅
        • 1.1 重写绘图事件
        • 1.2 设置窗口大小、图标、标题
        • 1.3 设置开始按钮样式
      • 2. 游戏关卡选择
        • 2.1 创建GameSelect类
        • 2.2 连接按钮和窗口跳转
      • 3. 游戏房间
        • 3.1 创建GameRoom类
        • 3.2 对游戏房间数据结构进行封装
        • 3.3 初始化游戏房间界面
        • 3.4 绘制界面窗口
        • 3.5 蛇的移动
        • 3.6 绘制蛇头身体尾巴
        • 3.6 绘制食物与分数
        • 3.7 判定游戏结束
        • 3.8 随机生成食物节点
        • 3.9 创建游戏开始和暂停按钮
        • 3.10 实现定时器的超时槽函数
        • 3.11 设置游戏退出按钮
        • 3.12 获取历史战绩
    • 四、项目源码获取
      • 1. 网盘链接
      • 2. Gitee链接


一、项目介绍及演示

1. 项目介绍

贪吃蛇游戏规则:简单来说,贪吃蛇游戏规则是玩家通过四个方向键来控制蛇的移动控制其在地图上吃豆子。蛇运动过程中撞到墙壁或蛇身,则立即结束游戏。

当前是贪吃蛇1.0版本,后续会对贪吃蛇游戏进行美化及增加更多功能,尽情期待。
在贪吃蛇2.0中会对项目进行图片的美化,及键盘快捷键的添加。

2. 项目演示

动图演示【GIF动图演示】
在这里插入图片描述

3. 窗口介绍

3.1 游戏大厅窗口

在首页中有历史战绩、开始游戏两个按钮。历史战绩用于展示以前游玩的历史记录;开始游戏用于跳转到游戏关卡选择难度界面。
在这里插入图片描述

3.2 游戏关卡选择窗口

在这里插入图片描述

3.3 游戏房间窗口

在这里插入图片描述


二、创建项目及资源配置

1. 创建项目(QWidget)

在桌面上创建一个名为Snake的文件夹,用于存放项目代码

在这里插入图片描述
打开Qt,点击新建项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 资源配置(图片声音素材)

在上述创建完成后,新建一个qrc文件,步骤如下
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
完成上述步骤,将素材包复制到项目中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


三、项目实现

1. 游戏大厅

1.1 重写绘图事件

在gamehall.h文件中,进行重写绘图事件函数的声明

在这里插入图片描述

鼠标当到painEvent函数上点击Alt+Enter(回车),为painEvent函数添加定义

在这里插入图片描述
在上述过程后,开始编辑painEvent函数。
第一步,先实例化画家,使用QPainter painter(this)实例化一个画家,this是让画家在当前窗口(gamehall)进行绘制。注意在使用QPainter需要包含头文件#include<QPainter>
第二步,再实例化绘图设备,将图片加载到绘图设备中。注意在使用QPixmap需要包含头文件#include<QPixmap>
第三步,再进行绘画,使用drawPixmap()方法,参数1和参数2,表示绘制开始的坐标;参数3,表示绘制的宽度;参数4,表示绘制的高度;参数5,表示绘制的图片。

void GameHall::paintEvent(QPaintEvent *event)
{//实例化画家,this:让画家在当前窗口进行绘制QPainter painter(this);//实例化绘图设备QPixmap pix(":/res/game_hall.png");//绘画 0,0从界面左上角开始绘画根据窗口的宽和高进行绘制painter.drawPixmap(0,0,this->width(),this->height(),pix);
}
1.2 设置窗口大小、图标、标题

第一步,先修改窗口的大小通过setFixedSize()方法将窗口的宽度设置为1000,高度设置为800。
第二步,设置窗口的图标先通过QIcon()将图片加载到项目中,再通过setWindowIcon()方法设置到窗口中。
第三步,设置窗口的标题通过setWindowTitle()方法将文字设置到窗口标题中。

GameHall::GameHall(QWidget *parent): QWidget(parent), ui(new Ui::GameHall)
{ui->setupUi(this);//设置窗口大小this->setFixedSize(1000,800);//设置窗口的图标this->setWindowIcon(QIcon(":/res/ico.png"));//设置窗口标题this->setWindowTitle("游戏大厅");
}
1.3 设置开始按钮样式

第一步,通过QPushButton创建一个游戏开始按钮,按钮文本设置为"开始游戏",this在父窗口中显示。
第二步,通过move移动按钮再窗口中的位置,消除按钮的边框。
第三步,修改按钮中的文本样式,需要先创建一个字体样式(字体为黑体,大小为20像素),最后通过setFont方法将字体样式加载到按钮中。

GameHall::GameHall(QWidget *parent): QWidget(parent), ui(new Ui::GameHall)
{ui->setupUi(this);//设置窗口大小this->setFixedSize(1000,800);//设置窗口的图标this->setWindowIcon(QIcon(":/res/ico.png"));//设置窗口标题this->setWindowTitle("游戏大厅");//添加开始游戏按钮QPushButton * startButton = new QPushButton("开始游戏",this);//设置按钮的位置startButton->move(450,600);//消除按钮边框startButton->setStyleSheet("QPushButton{border:0px}");//创建字体样式QFont font("黑体", 20);//将字体样式加入到按钮文本中startButton->setFont(font);}

点击运行,游戏大厅窗口界面就完成了,如下图
在这里插入图片描述

2. 游戏关卡选择

2.1 创建GameSelect类

先创建一个新的类,名为为GameSelect,基类选择QWidget
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 连接按钮和窗口跳转

在gamehall.cpp中进行编辑按钮的信号和槽,实现点击按钮跳转至关卡选择窗口
第一步,先创建出一个GameSelect窗口,在创建时要包含头文件#include "gameselect.h"
第二步,进行连接使用connnect()方法进行信号和槽函数之间的连接,使用Lambda表达式进行槽函数的编写。
第三步,编辑Lambda表达式,使用close()方法关闭当前窗口。
第四步,将关卡选择窗口设置为同游戏大厅窗口大小相同。
第五步,打开游戏关卡选择窗口。
第六步,给按钮添加点击音效,首先在.pro文件中添加multimedia,然后使用play()进行添加音效。
在这里插入图片描述

#include "gamehall.h"
#include "ui_gamehall.h"
#include "gameselect.h"
#include <QPainter>
#include <QPixmap>
#include <QIcon>
#include <QPushButton>
#include <QFont>
#include <QSound>
GameHall::GameHall(QWidget *parent): QWidget(parent), ui(new Ui::GameHall)
{ui->setupUi(this);//设置窗口大小this->setFixedSize(1000,800);//设置窗口的图标this->setWindowIcon(QIcon(":/res/ico.png"));//设置窗口标题this->setWindowTitle("游戏大厅");//添加开始游戏按钮QPushButton * startButton = new QPushButton("开始游戏",this);//设置按钮的位置startButton->move(450,600);//消除按钮边框startButton->setStyleSheet("QPushButton{border:0px}");//创建字体样式QFont font("黑体", 20);//将字体样式加入到按钮文本中startButton->setFont(font);//新建GameSelect窗口GameSelect * gameSelect = new GameSelect;//Lambda表达式connect(startButton,&QPushButton::clicked,[=](){//先关闭当前窗口this->close();//设置gameSelect窗口大小跟gamehall窗口大小一样gameSelect->setGeometry(this->geometry());//打开gameselect窗口gameSelect->show();//添加按钮点击的音效QSound::play(":/res/clicked.wav");});}

编写gameselect.h文件,同游戏大厅步骤,这里不重复进行介绍,,详细看下下方代码注释。

在这里插入图片描述

#include "gameselect.h"
#include "gamehall.h"
#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QIcon>
#include <QSound>
GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{//设置窗口大小this->setFixedSize(1000,800);//设置窗口的图标this->setWindowIcon(QIcon(":/res/ico.png"));//设置窗口标题this->setWindowTitle("关卡选择");//创建返回按钮QPushButton * returnbutton = new QPushButton(this);returnbutton->resize(50,50);returnbutton->setIcon(QIcon(":/res/back.png"));returnbutton->setIconSize(returnbutton->size());returnbutton->move(900,700);//建立信号和槽函数的联系connect(returnbutton,&QPushButton::clicked,[=](){//创建游戏大厅窗口GameHall * gamehall = new GameHall;//关闭当前窗口this->close();//展开游戏大厅窗口gamehall->show();//添加音效QSound::play(":/res/clicked.wav");});//创建文本样式QFont font("黑体",30);//创建简单难度按钮QPushButton * simplebutton = new QPushButton("简单模式",this);//将样式设置到按钮中simplebutton->setFont(font);//设置按钮在窗口中的位置simplebutton->move(400,170);//进行信号与槽的连接//创建普通难度按钮QPushButton * commonbutton = new QPushButton("普通模式",this);//将样式设置到按钮中commonbutton->setFont(font);//设置按钮在窗口中的位置commonbutton->move(400,270);//创建困难难度按钮QPushButton * difficultybutton = new QPushButton("困难模式",this);//将样式设置到按钮中difficultybutton->setFont(font);//设置按钮在窗口中的位置difficultybutton->move(400,370);//创建历史记录按钮QPushButton * hisbutton = new QPushButton("历史记录",this);//将样式设置到按钮中hisbutton->setFont(font);//设置按钮在窗口中的位置hisbutton->move(400,470);}void GameSelect::paintEvent(QPaintEvent *event)
{//实例化画家,this:让画家在当前窗口进行绘制QPainter painter(this);//实例化绘图设备QPixmap pix(":/res/game_select.png");//绘画painter.drawPixmap(0,0,this->width(),this->height(),pix);
}

3. 游戏房间

3.1 创建GameRoom类

根据上面步骤后,新建GameRoom类
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 对游戏房间数据结构进行封装
#ifndef GAMEROOM_H
#define GAMEROOM_H#include <QWidget>
#include<QSound>
enum class SnakeDirect{UP=0,DOWN,LEFT,RIGHT};
class GameRoom : public QWidget
{Q_OBJECT
public:explicit GameRoom(QWidget *parent = nullptr);//重写绘图事件void paintEvent(QPaintEvent *event);void moveUp(); //向上移动void moveDown();//向下移动void moveLeft();//向左移动void moveRight();//向右移动bool checkFail();//判断游戏结束void createNewFood();//创建食物void setTimeout(int timeout){moveTimeout =timeout;}private:const int KSnakeNodeWidth = 20;  //蛇节点的宽度const int KSnakeNodeHeight = 20; //蛇节点的高度const int KDefaultTimeout =200;  //蛇的默认移动速度QList<QRectF> snakeList; //表示贪吃蛇链表QRectF foodRect;  //表示食物节点SnakeDirect moveDirect = SnakeDirect::UP; //设置蛇移动方向默认向上QTimer *timer; //定时器bool isGameStart =false; //表示是否开始游戏QSound *sound;int moveTimeout =  KDefaultTimeout;};#endif // GAMEROOM_H
3.3 初始化游戏房间界面
//设置窗口大小this->setFixedSize(1000,800);//设置窗口的图标this->setWindowIcon(QIcon(":/res/ico.png"));//设置窗口标题this->setWindowTitle("游戏房间");
3.4 绘制界面窗口
void GameRoom::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPixmap pix;pix.load(":/res/game_room.png");painter.drawPixmap(0,0,800,800,pix);pix.load(":/res/bg1.png");painter.drawPixmap(800,0,200,850,pix);
}
3.5 蛇的移动
//创建上下左右按钮QPushButton * up = new QPushButton("↑",this);QPushButton * down = new QPushButton("↓",this);QPushButton * left = new QPushButton("←",this);QPushButton * right = new QPushButton("→",this);up->move(880,400);down->move(880,480);left->move(840,440);right->move(920,440);up->setFont(font);down->setFont(font);left->setFont(font);right->setFont(font);up->setStyleSheet("QPushButton{border:0px}");down->setStyleSheet("QPushButton{border:0px}");left->setStyleSheet("QPushButton{border:0px}");right->setStyleSheet("QPushButton{border:0px}");//按钮控制移动方向,不能直接掉头connect(up,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::DOWN)moveDirect = SnakeDirect::UP;});connect(down,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::UP)moveDirect = SnakeDirect::DOWN;});connect(left,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::RIGHT)moveDirect = SnakeDirect::LEFT;});connect(right,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::LEFT)moveDirect = SnakeDirect::RIGHT;});
void GameRoom::moveUp()
{QPointF leftTop; //左上角坐标QPointF rightBottom; //右下角坐标auto snakeNode = snakeList.front();//头int headX = snakeNode.x();int headY = snakeNode.y();if(headY<0){leftTop = QPointF(headX, this->height()- KSnakeNodeHeight);}else {leftTop=QPointF(headX,headY-KSnakeNodeHeight);}rightBottom = leftTop + QPointF(KSnakeNodeWidth,KSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightBottom));
}void GameRoom::moveDown()
{QPointF leftTop; //左上角坐标QPointF rightBottom; //右下角坐标auto snakeNode = snakeList.front();//头int headX = snakeNode.x();int headY = snakeNode.y();if(headY>this->height()){leftTop = QPointF(headX,0);}else {leftTop=snakeNode.bottomLeft();}rightBottom = leftTop + QPointF(KSnakeNodeWidth,KSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightBottom));
}void GameRoom::moveLeft()
{QPointF leftTop; //左上角坐标QPointF rightBottom; //右下角坐标auto snakeNode = snakeList.front();//头int headX = snakeNode.x();int headY = snakeNode.y();if(headX<0){leftTop=QPointF(800-KSnakeNodeWidth,headY);}else{leftTop=QPointF(headX-KSnakeNodeWidth,headY);}rightBottom = leftTop + QPointF(KSnakeNodeWidth,KSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightBottom));
}void GameRoom::moveRight()
{QPointF leftTop; //左上角坐标QPointF rightBottom; //右下角坐标auto snakeNode = snakeList.front();//头int headX = snakeNode.x();int headY = snakeNode.y();if(headX>800-2*KSnakeNodeWidth){leftTop=QPointF(0,headY);}else{leftTop=snakeNode.topRight();}rightBottom = leftTop + QPointF(KSnakeNodeWidth,KSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightBottom));
}
3.6 绘制蛇头身体尾巴
//绘制蛇//蛇头if(moveDirect==SnakeDirect::UP){pix.load(":/res/up.png");}else if (moveDirect==SnakeDirect::DOWN) {pix.load(":/res/down.png");}else if(moveDirect==SnakeDirect::LEFT){pix.load(":/res/left.png");}else{pix.load(":/res/right.png");}auto snakeHead = snakeList.front();painter.drawPixmap(snakeHead.x(),snakeHead.y(),snakeHead.width(),snakeHead.height(),pix);//蛇身pix.load(":/res/Bd.png");for(int i = 1; i < snakeList.size()-1; i++){auto node = snakeList.at(i);painter.drawPixmap(node.x(),node.y(),node.width(),node.height(),pix);}//蛇尾auto snakeTail = snakeList.back();painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeTail.width(),snakeTail.height(),pix);
3.6 绘制食物与分数
//绘制食物节点//先进行加载食物pix.load(":/res/food.bmp");painter.drawPixmap(foodRect.x(),foodRect.y(),foodRect.width(),foodRect.height(),pix);//绘制分数pix.load(":res/sorce_bg.png");painter.drawPixmap(this->width()*0.85,this->height()*0.03,100,50,pix);QPen pen;pen.setColor(Qt::black);painter.setPen(pen);QFont font("黑体",22);painter.setFont(font);painter.drawText(this->width()*0.9,this->height()*0.08,QString("%1").arg(snakeList.size()));//往文件中写分数int c = snakeList.size();QFile file("C:/Users/26256/Desktop/his.txt");if(file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream out(&file);int num = c;out << num;file.close();}
3.7 判定游戏结束
bool GameRoom::checkFail()
{for(int i=0;i < snakeList.size();i++){for(int j=i+1;j < snakeList.size();j++){if(snakeList.at(i) == snakeList.at(j)){return true;}}}return false;
}
3.8 随机生成食物节点
void GameRoom::createNewFood()
{foodRect=QRectF(qrand() %(800/KSnakeNodeWidth)*KSnakeNodeWidth,qrand() %(this->height()/KSnakeNodeHeight)*KSnakeNodeHeight,KSnakeNodeWidth,KSnakeNodeHeight);}
3.9 创建游戏开始和暂停按钮
//开始游戏   结束游戏QPushButton * startButton = new QPushButton("开始",this);QPushButton *failButton = new QPushButton("暂停",this);startButton->move(860,100);failButton->move(860,150);startButton->setFont(font2);failButton->setFont(font2);connect(startButton,&QPushButton::clicked,[=](){isGameStart=true;timer->start(moveTimeout);sound = new QSound(":res/Trepak.wav");sound->play();sound->setLoops(-1);});connect(failButton,&QPushButton::clicked,[=](){isGameStart=false;timer->stop();sound->stop();
3.10 实现定时器的超时槽函数
  timer = new QTimer(this);connect(timer,&QTimer::timeout,[=](){int cont =1;if(snakeList.front().intersects(foodRect)){createNewFood();cont++;QSound::play(":/res/eatfood.wav");}while(cont--){switch (moveDirect) {case SnakeDirect::UP :moveUp();break;case SnakeDirect::DOWN:moveDown();break;case SnakeDirect::LEFT:moveLeft();break;case SnakeDirect::RIGHT:moveRight();break;}}snakeList.pop_back();update();});
3.11 设置游戏退出按钮
//退出游戏按钮QPushButton *backButton = new QPushButton("退出",this);backButton->move(860,700);backButton->setFont(font2);QMessageBox * messbox = new QMessageBox(this);QPushButton * ok = new QPushButton("ok");QPushButton * no = new QPushButton("no");messbox->addButton(ok,QMessageBox::AcceptRole);messbox->addButton(no,QMessageBox::ResetRole);messbox->setText("确定要退出游戏吗?");connect(backButton,&QPushButton::clicked,[=](){messbox->show();messbox->exec();QSound::play("clicked.wav");GameSelect* select = new GameSelect;if(messbox->clickedButton()==ok){this->close();select->show();}else{messbox->close();}});
3.12 获取历史战绩
//创建历史记录按钮QPushButton * hisbutton = new QPushButton("历史记录",this);//将样式设置到按钮中hisbutton->setFont(font);//设置按钮在窗口中的位置hisbutton->move(400,470);connect(hisbutton,&QPushButton::clicked,[=](){QWidget * widget = new QWidget();widget->setFixedSize(200,80);widget->setWindowTitle("历史战绩");QTextEdit * edit = new QTextEdit(widget);edit->setFixedSize(200,80);edit->setFont(font);QFile file("C:/Users/26256/Desktop/his.txt");file.open(QIODevice::ReadOnly);QTextStream in(&file);int data = in.readLine().toInt();edit->append("得分为:");edit->append(QString::number(data));widget->show();});

四、项目源码获取

1. 网盘链接

百度网盘:https://pan.baidu.com/s/1Vm1aJ6AtyzfPdYSCIC0ygg?pwd=duck
提取码:duck

2. Gitee链接

Gitee链接:Qt贪吃蛇小游戏项目代码


在这里插入图片描述

这篇关于【Qt项目专栏】贪吃蛇小游戏1.0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1070075

相关文章

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

QT Creator配置Kit的实现示例

《QTCreator配置Kit的实现示例》本文主要介绍了使用Qt5.12.12与VS2022时,因MSVC编译器版本不匹配及WindowsSDK缺失导致配置错误的问题解决,感兴趣的可以了解一下... 目录0、背景:qt5.12.12+vs2022一、症状:二、原因:(可以跳过,直奔后面的解决方法)三、解决方

SpringBoot通过main方法启动web项目实践

《SpringBoot通过main方法启动web项目实践》SpringBoot通过SpringApplication.run()启动Web项目,自动推断应用类型,加载初始化器与监听器,配置Spring... 目录1. 启动入口:SpringApplication.run()2. SpringApplicat

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

在ASP.NET项目中如何使用C#生成二维码

《在ASP.NET项目中如何使用C#生成二维码》二维码(QRCode)已广泛应用于网址分享,支付链接等场景,本文将以ASP.NET为示例,演示如何实现输入文本/URL,生成二维码,在线显示与下载的完整... 目录创建前端页面(Index.cshtml)后端二维码生成逻辑(Index.cshtml.cs)总结

Spring Boot项目如何使用外部application.yml配置文件启动JAR包

《SpringBoot项目如何使用外部application.yml配置文件启动JAR包》文章介绍了SpringBoot项目通过指定外部application.yml配置文件启动JAR包的方法,包括... 目录Spring Boot项目中使用外部application.yml配置文件启动JAR包一、基本原理

Springboot项目登录校验功能实现

《Springboot项目登录校验功能实现》本文介绍了Web登录校验的重要性,对比了Cookie、Session和JWT三种会话技术,分析其优缺点,并讲解了过滤器与拦截器的统一拦截方案,推荐使用JWT... 目录引言一、登录校验的基本概念二、HTTP协议的无状态性三、会话跟android踪技术1. Cook

springboot项目中集成shiro+jwt完整实例代码

《springboot项目中集成shiro+jwt完整实例代码》本文详细介绍如何在项目中集成Shiro和JWT,实现用户登录校验、token携带及接口权限管理,涉及自定义Realm、ModularRe... 目录简介目的需要的jar集成过程1.配置shiro2.创建自定义Realm2.1 LoginReal

Qt中实现多线程导出数据功能的四种方式小结

《Qt中实现多线程导出数据功能的四种方式小结》在以往的项目开发中,在很多地方用到了多线程,本文将记录下在Qt开发中用到的多线程技术实现方法,以导出指定范围的数字到txt文件为例,展示多线程不同的实现方... 目录前言导出文件的示例工具类QThreadQObject的moveToThread方法实现多线程QC