编辑
2023-11-10
学习
00
请注意,本文编写于 404 天前,最后修改于 320 天前,其中某些信息可能已经过时。

使用状态机可以很方便的实现状态之间的切换,以及切换时的动作

一下是纯C++实现的状态机, 以及在QT中的切换效果

C++
#include <iostream> #include <unordered_map> class StateMachine { public: StateMachine() : currentStateName("") {} void addState(const std::string& name, const std::function<void()>& stateFunction) { states[name] = stateFunction; } void addTransition(const std::string& from, const std::string& to, const std::function<bool()>& transitionFunction) { transitions[from][to] = transitionFunction; } void start(const std::string& initialState) { currentStateName = initialState; if (states.find(currentStateName) != states.end()) { states[currentStateName](); } else { std::cerr << "Invalid initial state: " << initialState << std::endl; } } void triggerTransition() { if (transitions.find(currentStateName) != transitions.end()) { for (const auto& entry : transitions[currentStateName]) { if (entry.second()) { nextStateName = entry.first; return; } } } nextStateName = ""; // No valid transition found } void updateState() { if (!nextStateName.empty()) { currentStateName = nextStateName; if (states.find(currentStateName) != states.end()) { states[currentStateName](); } else { std::cerr << "Invalid state: " << currentStateName << std::endl; } nextStateName = ""; } } std::string getCurrentState() const { return currentStateName; } std::string getNextState() const { return nextStateName; } private: std::unordered_map<std::string, std::function<void()>> states; std::unordered_map<std::string, std::unordered_map<std::string, std::function<bool()>>> transitions; std::string currentStateName; std::string nextStateName; };

QT 代码

头文件

C++
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QPropertyAnimation> #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 slots: void on_pushButton_clicked(); private slots: void onAnimationFinished(); private: Ui::MainWindow *ui; StateMachine stateMachine; QPropertyAnimation* positionAnimation; bool positionAnimationing {false}; }; #endif // MAINWINDOW_H

CPP

C++
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 在 MainWindow 的构造函数中初始化 positionAnimation positionAnimation = new QPropertyAnimation(ui->stateobj, "pos", this); positionAnimation->setDuration(400); // 设置动画持续时间为500毫秒 positionAnimation->setEasingCurve(QEasingCurve::InOutBack); connect(positionAnimation, &QPropertyAnimation::finished, this, &MainWindow::onAnimationFinished); stateMachine.addState("StateA", [&]() { ui->stateobj->setText("State A");std::cout << "State A" << std::endl; }); stateMachine.addState("StateB", [&]() { ui->stateobj->setText("State B");std::cout << "State B" << std::endl; }); stateMachine.addState("StateC", [&]() { ui->stateobj->setText("State C");std::cout << "State C" << std::endl; }); stateMachine.addTransition("StateA", "StateB", [&]() { std::cout << "Transition from A to B" << std::endl; int x = 0; int y = height() / 2 - ui->stateobj->height() / 2; positionAnimation->setEndValue(QPoint(x, y)); // 左边中间位置 return true; // Allow transition }); stateMachine.addTransition("StateB", "StateC", [&]() { std::cout << "Transition from B to C" << std::endl; int x = 0; int y = height() - ui->stateobj->height(); positionAnimation->setEndValue(QPoint(x, y)); // 左下角 return true; // Allow transition }); stateMachine.addTransition("StateC", "StateA", [&]() { std::cout << "Transition from C to A" << std::endl; positionAnimation->setEndValue(QPoint(0, 0)); return true; // Allow transition }); stateMachine.start("StateA"); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { if(!positionAnimationing) { stateMachine.triggerTransition(); if (!stateMachine.getNextState().empty()) { stateMachine.updateState(); } // 启动动画 positionAnimation->start(); positionAnimationing = true; } } void MainWindow::onAnimationFinished() { // 在动画结束时执行的操作 positionAnimationing = false; }

效果

Animation.gif

本文作者:beiklive

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!