QStateMachine
QState 提供了一種強大且靈活的方式來表示狀態機中的狀態,通過與狀態機類(QStateMachine)和轉換類(QSignalTransition, QEventTransition)結合,可以實現復雜的狀態邏輯和用戶交互。合理使用嵌套狀態機、信號轉換、動作與動畫、歷史狀態和定時器事件等功能,可以增強應用的交互性和視覺效果。在實際應用中,通過優化狀態邏輯和轉換規則,可以實現豐富和動態的狀態管理功能。注意設置轉換條件、信信號槽連接和事件處理邏輯,確保狀態轉換的正確性和高效性。結合其他 Qt 類和方法,可以實現更多高級功能和應用場景,提高應用的靈活性和可維護性。
官方文檔參考:https://doc.qt.io/archives/qt-6.6/qtstatemachine-cpp-guide.html
Qt Class Hierarchy 類繼承關系圖 https://doc.qt.io/qt-6/hierarchy.html
案例 Demo: 上下班打卡
#include <QStateMachine>
qmake: QT += statemachine
CMake: find_package(Qt6 REQUIRED COMPONENTS StateMachine)
target_link_libraries(mytarget PRIVATE Qt6::StateMachine)
// mainwindow.h
#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui{class MainWindow;}
QT_END_NAMESPACEclass QStateMachine;
class MainWindow : public QMainWindow {Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();
signals:void isWorkDay(bool);void inOfficeArea(bool);void shouldRemind(bool);void remindFinished();
private:void init();
private slots:void checkConditions();
private:Ui::MainWindow *ui;QStateMachine *machine;QTimer *checkTimer;
};#endif // MAINWINDOW_H
// mainwindow.cpp
#include <QStateMachine> // QT += statemachine or Qt6::StateMachine
#include <QTimer>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), machine(new QStateMachine(this))
{ui->setupUi(this);init();
}
void MainWindow::init()
{ // 1.創建狀態: 空閑->工作日->在辦公區域->提醒//若對狀態進行分組:創建狀態時指定正確的父狀態QState *idleState = new QState(machine);QState *workdayState = new QState(machine);QState *locationState = new QState(machine);QState *remindState = new QState(machine);machine->setInitialState(idleState);//2. 設置狀態轉換idleState->addTransition(this, &MainWindow::isWorkDay, workdayState);workdayState->addTransition(this, &MainWindow::inOfficeArea, locationState);locationState->addTransition(this, &MainWindow::shouldRemind, remindState);remindState->addTransition(this, &MainWindow::remindFinished, idleState);// 比如remindState狀態進入時的操作connect(remindState, &QState::entered, this,[=](){ui->label->setText("打卡提醒, 請及時打卡!");ui->pushButton->setEnabled(true);emit remindFinished();});machine->start();// 設置定時檢查--純模擬checkTimer = new QTimer(this);connect(checkTimer, &QTimer::timeout, this, &MainWindow::checkConditions);checkTimer->start(3000);//打卡按鈕connect(ui->pushButton,&QPushButton::clicked,this,[=](){auto t=ui->timeEdit->time();QString text;if(t >= QTime(6,45) && t <= QTime(9,30)) text = "上班";else if(t > QTime(9,30) && t < QTime(12,0)) text = "上班遲到";else if(t > QTime(13,30) && t < QTime(18,0) )text = "提前下班";else if(t >= QTime(18,0)) text = "下班";ui->label->setText(t.toString() + text + " 打卡成功");});
}void MainWindow::checkConditions()
{QTime t = ui->timeEdit->time();ui->pushButton->setEnabled(false);// 1.判斷工作日 QDate::currentDate().dayOfWeek() <= 5; // 周一到周五bool workday = ui->ckBankHoliday->isChecked() ? false :ui->ckWorkDay->isChecked() ? true : false;emit isWorkDay(workday);if(!workday){ui->label->setText(t.toString() + " 假期,無需打卡");return;}// 2.判斷位置 (實際用QGeoPositionInfoSource)bool inOffice = ui->ckInOfficeArea->isChecked(); // 在辦公區域emit inOfficeArea(inOffice);if(!inOffice){ui->label->setText(t.toString() + " 不在辦公區域,無法打卡");return;}//3.上班前/下班后提醒打卡bool isWorkTime = (t >= QTime(6,45) && t <= QTime(23,59));if(!isWorkTime){ui->label->setText(t.toString() + " 無法打卡\n打卡時間 6:45-9:30 18:00-22:30");return;}emit shouldRemind(isWorkTime);
}
其它大佬
https://blog.csdn.net/weixin_43510208/article/details/147960966