首页 > 其他分享 >QT使用状态机实现qml页面切换配置化

QT使用状态机实现qml页面切换配置化

时间:2024-12-24 15:35:58浏览次数:7  
标签:states const QT 状态机 QString include qmlPath qml

1.首先创建配置文件(JSON 格式):

// states_config.json
{
"states": [
{
"name": "InitState",
"qmlPath": "qrc:/qml/InitPage.qml",
"transitions": [
{
"event": "init_completed",
"target": "MainState"
}
]
},
{
"name": "MainState",
"qmlPath": "qrc:/qml/MainPage.qml",
"transitions": [
{
"event": "to_settings",
"target": "SettingsState"
}
]
},
{
"name": "SettingsState",
"qmlPath": "qrc:/qml/SettingsPage.qml",
"transitions": [
{
"event": "back",
"target": "MainState"
}
]
}
]
}

2.创建状态机管理类:

// statemanager.h
#ifndef STATEMANAGER_H
#define STATEMANAGER_H

#include <QObject>
#include <QStateMachine>
#include <QState>
#include <QMap>
#include <QJsonObject>

class StateManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QString currentQmlPath READ currentQmlPath NOTIFY currentQmlPathChanged)

public:
explicit StateManager(QObject *parent = nullptr);

void loadConfig(const QString &configPath);
QString currentQmlPath() const;
Q_INVOKABLE void triggerEvent(const QString &event);

signals:
void currentQmlPathChanged(const QString &path);
void stateChanged(const QString &stateName);

private:
void setupState(const QJsonObject &stateConfig);

QStateMachine m_machine;
QMap<QString, QState*> m_states;
QMap<QString, QString> m_stateQmlPaths;
QString m_currentQmlPath;
};

#endif // STATEMANAGER_H

 

// statemanager.cpp
#include "statemanager.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>

StateManager::StateManager(QObject *parent)
: QObject(parent)
{
}

void StateManager::loadConfig(const QString &configPath)
{
QFile file(configPath);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open config file:" << configPath;
return;
}

QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
QJsonArray states = doc.object()["states"].toArray();

// 创建所有状态
for (const QJsonValue &stateValue : states) {
QJsonObject stateObj = stateValue.toObject();
setupState(stateObj);
}

// 设置转换
for (const QJsonValue &stateValue : states) {
QJsonObject stateObj = stateValue.toObject();
QString stateName = stateObj["name"].toString();
QState *state = m_states[stateName];

QJsonArray transitions = stateObj["transitions"].toArray();
for (const QJsonValue &transValue : transitions) {
QJsonObject transObj = transValue.toObject();
QString event = transObj["event"].toString();
QString target = transObj["target"].toString();

if (m_states.contains(target)) {
state->addTransition(this,
SIGNAL(eventTriggered(QString)),
m_states[target]);
}
}
}

// 启动状态机
m_machine.start();
}

void StateManager::setupState(const QJsonObject &stateConfig)
{
QString stateName = stateConfig["name"].toString();
QString qmlPath = stateConfig["qmlPath"].toString();

QState *state = new QState(&m_machine);
m_states[stateName] = state;
m_stateQmlPaths[stateName] = qmlPath;

connect(state, &QState::entered, this, [this, qmlPath, stateName]() {
m_currentQmlPath = qmlPath;
emit currentQmlPathChanged(qmlPath);
emit stateChanged(stateName);
});
}

void StateManager::triggerEvent(const QString &event)
{
emit eventTriggered(event);
}

QString StateManager::currentQmlPath() const
{
return m_currentQmlPath;
}

3. 主窗口 QML 文件:

// main.qml
import QtQuick 2.15
import QtQuick.Window 2.15

Window {
visible: true
width: 800
height: 600
title: qsTr("State Machine Demo")

Loader {
id: pageLoader
anchors.fill: parent
source: stateManager.currentQmlPath
}
}

4.示例页面 QML 文件:

// InitPage.qml
import QtQuick 2.15

Rectangle {
color: "lightblue"

Text {
anchors.centerIn: parent
text: "Init Page"
}

MouseArea {
anchors.fill: parent
onClicked: {
stateManager.triggerEvent("init_completed")
}
}
}

// MainPage.qml
import QtQuick 2.15

Rectangle {
color: "lightgreen"

Text {
anchors.centerIn: parent
text: "Main Page"
}

MouseArea {
anchors.fill: parent
onClicked: {
stateManager.triggerEvent("to_settings")
}
}
}

 

5.在 main.cpp 中设置:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "statemanager.h"

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);

StateManager stateManager;
stateManager.loadConfig(":/config/states_config.json");

QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("stateManager", &stateManager);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

return app.exec();
}

6.项目文件 (qml.qrc):

<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>qml/InitPage.qml</file>
<file>qml/MainPage.qml</file>
<file>qml/SettingsPage.qml</file>
<file>config/states_config.json</file>
</qresource>
</RCC>

使用这个实现的优点:

 

配置驱动:

 
  • 状态和转换通过配置文件定义
 
  • 易于修改和维护
 
  • 可以动态加载不同配置
 

解耦:

 
  • QML 页面与状态逻辑分离
 
  • 状态转换逻辑集中管理
 
  • 页面可以独立开发和测试
 

扩展性:

 
  • 易于添加新状态和页面
 
  • 可以添加状态转换条件
 
  • 可以添加状态进入/退出动作
 

调试友好:

 
  • 状态变化可以记录日志
 
  • 可以监控状态转换
 
  • 配置文件易于检查
 

可以根据需要扩展功能:

 
  • 添加状态转换动画
 
  • 添加状态历史
 
  • 添加条件转换
 
  • 添加状态数据
 
  • 添加错误处理
 
  • 添加状态持久化
 

使用时注意:

 
  • 确保配置文件格式正确
 
  • 处理文件加载错误
 
  • 验证状态转换的有效性
 
  • 考虑添加状态转换的权限控制
 
  • 考虑添加状态转换的日志记录

标签:states,const,QT,状态机,QString,include,qmlPath,qml
From: https://www.cnblogs.com/lllion/p/18627771

相关文章

  • 嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
    此项目是基于人脸识别的考勤系统开发,包括如下模块:1、人脸识别考勤系统GUI界面设计,包括:(1)Qt环境(window环境/linux环境);(2)Qt工程创建分析;(3)Qt基本组件QwidgetQMainWindow,Qdialog,QLineEdit,Qlabel,QPushButton;(4)Qt界面布局,设计人脸识别考勤系统界面搭建;(5)考勤机界面设计(考勤......
  • Qt编程快速入门(1)Qt结构简介
    Qt构成Qt(/ˈkjuːt/,发音同“cute”)是一个跨平台的C++应用程序开发框架。广泛用于开发GUI程序,这种情况下又被称为部件工具箱。也可用于开发非GUI程序,例如控制台工具和服务器。-摘自维基百科Qt可以在多个平台编译运行,包括Windows、Linux、MacOS,其运行时的表现取决于操作系统的U......
  • VScode + cmake编写Qt程序
    本机环境Ubuntu20.04Qt5.12.81.安装Vscode直接在官网下载对应的deb包安装即可。下载后在deb包所在目录执行如下命令安装deb包。sudodpkg-i安装包名.deb然后在应用程序中应该就有了Vscode的图标了。2.安装cmake与gccg++先安装cmakesudoapt-getinstall......
  • QTreeView + 自定义json模型
    QTreeView使用自定义json模型前言QTreeView+自定义json模型QTreeView使用自定义json模型支持节点插入删除二、代码//QJsonModel.h#ifndefQJSONMODEL_H#defineQJSONMODEL_H#include<QAbstractItemModel>#include<QJsonDocument>#include<QJsonObject>#i......
  • QML实现图片阴影效果
    QML实现图片阴影效果importQtQuickWindow{width:640height:480visible:truetitle:qsTr("GrayImage")Image{id:no_shadowx:100y:100source:'assets/Balatro.png'}Border......
  • Qt编写机器码秘钥控制/日期防篡改/离线使用/硬件标识/运行时间/数量控制/批量更新秘钥
    一、前言说明搞软件开发一直追求精益求精的目标,从第一版的秘钥生成器到今天这个版本,经历了十年的时间,最初的版本做的非常简陋,就是搞了个异或加密,控制运行时间,后面又增加设备数量的控制,然后就是到期时间的限制。这种有个巨大缺陷就是可复制性,如果将授权的秘钥文件,拷贝到其他电脑也......
  • ubuntu20.04 RTKLIB QT版构建流程记录
    rtklib是GNSS领域有名的开源软件,在此记录成功构建QT版的步骤。0系统信息话不多说,首先上一张neofetch图展示系统信息。我的系统是Ubuntu20.04.6,其他系统版本暂未尝试。1打开qtcreator由于系统安装了多个qtcreator,从终端打开QtCreator4.11.0之所以强调Creator版本,是因......
  • pyqt5之网格布局
    解决fromPyQt5importQtCorefromPyQt5.QtWidgetsimport*classDemo(QWidget):def__init__(self,parent=None):#这行代码调用了QWidget类的构造函数,以确保Demo类正确地继承了QWidget的属性和方法#初始化父类属性super(Demo,sel......
  • pyqt5线程龟兔赛跑
    哈哈哈#-*-coding:utf-8-*-#Formimplementationgeneratedfromreadinguifile'龟兔赛跑.ui'##Createdby:PyQt5UIcodegenerator5.15.9##WARNING:Anymanualchangesmadetothisfilewillbelostwhenpyuic5is#runagain.Donoteditt......
  • QT多媒体开发(二):播放音频
    简介QMediaPlayer可以用于播放经过压缩的音频文件,如MP3文件和WMA文件。QSoundEffect可以用于播放低延迟音效文件,例如无压缩的WAV文件。这两个类都可以用于播放本地文件和网络文件。QMediaPlayer与播放音频相关的接口函数如下:voidsetAudioOutput(QAudioOutput*o......