简介
本文章是基本Qt与C++实现一个抽奖小游戏,用到的知识点在此前发布的几篇文章。
下面是跳转链接:
【Qt控件之QLabel】用法及技巧
链接: https://blog.csdn.net/MrHHHHHH/article/details/133691441?spm=1001.2014.3001.5501
【Qt控件之QPushButton】用法及技巧
链接:
https://blog.csdn.net/MrHHHHHH/article/details/133692079?spm=1001.2014.3001.5501
【Qt控件之QDialog】用法及技巧
链接:
https://blog.csdn.net/MrHHHHHH/article/details/133721638?spm=1001.2014.3001.5501
【Qt控件之QMainWindow】用法及技巧
链接:
https://blog.csdn.net/MrHHHHHH/article/details/133722035?spm=1001.2014.3001.5501
【Qt控件之QTimer】用法及技巧
链接:
https://blog.csdn.net/MrHHHHHH/article/details/133722476?spm=1001.2014.3001.5501
实现方式
实现方式多种多样,但毕竟是小程序,需求明确(就没考虑操作及优化),功能简单,条理清晰,主要提供三种实现方式(此阶段未实现概率设置,之后再发布概率设置版本吧):
1. 基于while循环
- 示例:
先粘贴UI
.h
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_FORWARD_DECLARE_CLASS(C_DlgSetting)
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
// 退出
void slot_actQuit_triggered();
// 设置概率
void slot_actSetting_triggered();
// 开始
void slot_btnStart_clicked();
// 停止
void slot_btnStop__clicked();
private:
Ui::MainWindow *ui;
C_DlgSetting* m_pDlgSetting; // 概率设置类
bool m_bFlag = false;// 标志
};
#endif // MAINWINDOW_H
.cpp
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "DlgSetting.h"
#include <QTime>
#include <QThread>
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// m_pDlgSetting = new C_DlgSetting(this);
// 信号和槽
{
connect(ui->action_quit, &QAction::triggered, this, &MainWindow::slot_actQuit_triggered);
connect(ui->action_setting, &QAction::triggered, this, &MainWindow::slot_actSetting_triggered);
connect(ui->btn_start, &QPushButton::clicked, this, &MainWindow::slot_btnStart_clicked);
connect(ui->btn_stop, &QPushButton::clicked, this, &MainWindow::slot_btnStop__clicked);
}
// 声明随机数种子,不然就是伪随机(每次产生的随机数都一样)
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slot_actQuit_triggered()
{
close();
}
void MainWindow::slot_actSetting_triggered()
{
// m_pDlgSetting->exec();
}
void MainWindow::slot_btnStart_clicked()
{
if(m_bFlag)
{
return;
}
QStringList sl;
sl << "一等奖" << "二等奖" << "三等奖" << "四等奖" << "五等奖";
m_bFlag = true;
while (m_bFlag) {
int nRange = qrand() % 5;
ui->label_turn->setText(sl.at(nRange));
// 100ms转一次
QThread::msleep(100);
// 防止界面卡死
QCoreApplication::processEvents();
}
}
void MainWindow::slot_btnStop__clicked()
{
m_bFlag = false;
// 显示最终获奖结果
QString strRes = QString("最终结果: %1").arg(ui->label_turn->text());
ui->label_res->setText(strRes);
}
.main
cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
- 结果
- 实现思路
-- 设置UI,注意命名
-- 进行信号和槽连接
-- 实现"开始"和"结束"功能
-- 显示结果
2. 基于定时器
- 示例
UI显示与1.
是一样的,需借助QTimer
实现
QTimer 是 Qt 框架中的一个类,用于在特定的时间间隔后发出一个信号。它是 Qt
的事件循环系统的一部分,该系统允许程序在等待某些事件(如用户输入或定时器超时)时保持响应。
QTimer 的工作原理是将定时器的超时作为一个事件添加到 Qt
的事件队列中。当事件循环检测到定时器超时时,它就会发出预定的信号。这种机制允许 QTimer
在等待定时器超时时不会阻塞用户界面,因为事件循环可以继续处理其他事件,如用户输入或绘制事件。
相比之下,如果使用标准的 C++ 定时器,如
std::this_thread::sleep_for,在等待定时器超时时,当前线程将被阻塞,无法处理其他事件。这会导致用户界面无响应,给用户一种程序已经卡死的感觉。
直接粘贴相关代码:
.h
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
// 退出
void slot_actQuit_triggered();
// 开始
void slot_btnStart_clicked();
// 停止
void slot_btnStop__clicked();
// 定时器处理
void slot_timeout();
private:
Ui::MainWindow *ui;
bool m_bFlag = false;// 标志
QTimer* m_pTimer;// 定时器
};
#endif // MAINWINDOW_H
.cpp
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTime>
#include <QThread>
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pTimer = new QTimer(this);
// 处理
connect(m_pTimer, &QTimer::timeout, this, &MainWindow::slot_timeout);
// 信号和槽
{
connect(ui->action_quit, &QAction::triggered, this, &MainWindow::slot_actQuit_triggered);
connect(ui->btn_start, &QPushButton::clicked, this, &MainWindow::slot_btnStart_clicked);
connect(ui->btn_stop, &QPushButton::clicked, this, &MainWindow::slot_btnStop__clicked);
}
// 声明随机数种子,不然就是伪随机(每次产生的随机数都一样)
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slot_actQuit_triggered()
{
close();
}
void MainWindow::slot_btnStart_clicked()
{
// 此处可先判断定时器是否处于活动状态,如果是,则返回;否则,再启动
// ToDoSomething
{
}
m_pTimer->start(100);
}
void MainWindow::slot_btnStop__clicked()
{
m_pTimer->stop();
// 显示最终获奖结果
QString strRes = QString("最终结果: %1").arg(ui->label_turn->text());
ui->label_res->setText(strRes);
}
void MainWindow::slot_timeout()
{
QStringList sl;
sl << "一等奖" << "二等奖" << "三等奖" << "四等奖" << "五等奖";
int nRange = qrand() % 5;
ui->label_turn->setText(sl.at(nRange));
}
- 实现思路
-- 点击"开始",启动定时器
-- "定时器"实现界面刷新
-- 点击"结束",停止定时器,并将结果显示
3. 基于线程
- 实现思路(等之后发布线程文章后,实现)
-- 在主窗口创建一个线程对象
-- 点击"开始",将信号发送到线程中,用于更新几等奖
-- 线程将更新后的信息发送到主窗口
-- 主窗口动态显示
-- 点击"结束",停止线程,显示结果
go.