• QT状态机使用笔记1


    首先是简单的状态机使用。状态机里面包含不同的状态,状态之间可以切换。状态机的类是QStateMachine。 状态的类是QState。 在使用之前,需要在QT的pro配置文件中添加QT += statemachine。

    先声明状态机和状态。

    QStateMachine machine;
    QState *stop;
    QState *running;
    QState *pause;
    
    然后再实现:
    stop = new QState;
    running = new QState;
    pause = new Qstate;
    
    将状态添加到状态机:
    machine.addState(stop);
    machine.addState(running);
    machine.addState(pause);
    
    状态机里有多个状态,但不知道从哪里开始执行。我们需要指定一个初始的状态。
    machine.setInitialState(stop);
    
    状态之前需要切换,从一个状态变成另一个状态。我们需要告诉程序状态之间的切换关系,还有在什么状态下切换。
    在按钮按下时,从stop切换到running状态
    stop->addTransition(ui->changeStateButton, &QPushButton::clicked, running);
    在按钮按下时,从running切换到pause状态
    running->addTransition(ui->changeStateButton, &QPushButton::clicked, pause);
    在按钮按下时,从pause切换到running状态
    pause->addTransition(ui->changeStateButton, &QPushButton::clicked, running);
    
    然后,我们告诉状态机开始执行
    machine.start();
    
    好了,简单状态机完成,在UI上添加标签来显示状态值,开始运行程序,点击按钮。

    什么也没发生!因为状态切换时,没有伴随的效果,我们看不出状态发生了变化。下面我们为各个状态添加一些肉眼可见的行为。
    这里将状态和标签的text属性绑定起来,标签会根据状态来变更属性的值(属性有多种,可以在对应控件的帮助文档里找到)。
    stop->assignProperty(ui->stateLabel, "text", QString(tr("停止状态")));
    running->assignProperty(ui->stateLabel, "text", QString(tr("运行状态")));
    pause->assignProperty(ui->stateLabel, "text", QString(tr("暂停状态")));
    运行如下:

    状态切换关系如下图:

    一个简单的状态机完成了。

    代码如下:

    头文件

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include
    5. #include
    6. QT_BEGIN_NAMESPACE
    7. namespace Ui { class Widget; }
    8. QT_END_NAMESPACE
    9. class Widget : public QWidget
    10. {
    11. Q_OBJECT
    12. public:
    13. Widget(QWidget *parent = nullptr);
    14. ~Widget();
    15. private:
    16. Ui::Widget *ui;
    17. QStateMachine machine;
    18. QState *stop;
    19. QState *running;
    20. QState *pause;
    21. };
    22. #endif // WIDGET_H

    源文件

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent)
    4. : QWidget(parent)
    5. , ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. stop = new QState;
    9. running = new QState;
    10. pause = new QState;
    11. machine.addState(stop);
    12. machine.addState(running);
    13. machine.addState(pause);
    14. machine.setInitialState(stop);
    15. stop->addTransition(ui->changeStateButton, &QPushButton::clicked, running);
    16. running->addTransition(ui->changeStateButton, &QPushButton::clicked, pause);
    17. pause->addTransition(ui->changeStateButton, &QPushButton::clicked, running);
    18. machine.start();
    19. stop->assignProperty(ui->stateLabel, "text", QString(tr("停止状态")));
    20. running->assignProperty(ui->stateLabel, "text", QString(tr("运行状态")));
    21. pause->assignProperty(ui->stateLabel, "text", QString(tr("暂停状态")));
    22. }
    23. Widget::~Widget()
    24. {
    25. delete ui;
    26. }

    继续完善,状态切换可以有不同的操作出发,我们再增加一个状态复位按钮,让状态回到停止状态。

    增加如下代码,注意第二个参数也可以采用这种格式。将运行或暂停状态切换回停止状态。
    running->addTransition(ui->resumeButton, SIGNAL(clicked()), stop);
    pause->addTransition(ui->resumeButton, SIGNAL(clicked()), stop);

    假如这个状态切换伴随着其他操作比如歌曲的播放和暂停,那在按钮按下时,需要对应的操作。对于按钮来说,都是click状态,怎么知道是谁切换到谁呢?可以通过判断标签的属性来确定,但更好的办法是不同的状态切换时直接触发对应的处理。

    将stop的addTransition改造一下。 addTransition添加的参数可以是QSignalTransition类。QSignalTransition在初始化时,设置上关联的控件和控件动作。然后通过 setTargetState设置成将要变成的状态,通过triggered信号,来绑定触发时对应的行为(这里添加了一个槽函数)。再用stop状态添加新创建的QSignalTransition,完成状态切换的设置。

    这样在状态切换的同时,还会调用对应的处理函数。

    QSignalTransition *stopTorunning = new QSignalTransition(ui->changeStateButton, &QPushButton::clicked);

    stopTorunning->setTargetState(running);

    connect(stopTorunning, SIGNAL(triggered()), this, SLOT(stopToRunningSlot()));

    stop->addTransition(stopTorunning);

    为了直观的显示调用,将UI修改如下:

    槽函数的实现如下:

    void Widget::stopToRunningSlot()
    {
     ui->textBrowser->append(QString("停止到运行"));
    }

    运行一下程序

     

     将其他转换设置也作类似更改,得到如下程序:

    代码如下:

    头文件

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include
    5. #include
    6. QT_BEGIN_NAMESPACE
    7. namespace Ui { class Widget; }
    8. QT_END_NAMESPACE
    9. class Widget : public QWidget
    10. {
    11. Q_OBJECT
    12. public:
    13. Widget(QWidget *parent = nullptr);
    14. ~Widget();
    15. private slots:
    16. void stopToRunningSlot();
    17. void runningToPauseSlot();
    18. void pauseToRunningSlot();
    19. void runningToStopSlot();
    20. void pauseToStopSlot();
    21. private:
    22. Ui::Widget *ui;
    23. QStateMachine machine;
    24. QState *stop;
    25. QState *running;
    26. QState *pause;
    27. };
    28. #endif // WIDGET_H

    源文件

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. #include
    4. Widget::Widget(QWidget *parent)
    5. : QWidget(parent)
    6. , ui(new Ui::Widget)
    7. {
    8. ui->setupUi(this);
    9. stop = new QState;
    10. running = new QState;
    11. pause = new QState;
    12. machine.addState(stop);
    13. machine.addState(running);
    14. machine.addState(pause);
    15. machine.setInitialState(stop);
    16. //stop->addTransition(ui->changeStateButton, &QPushButton::clicked, running);
    17. QSignalTransition *stopTorunning = new QSignalTransition(ui->changeStateButton, &QPushButton::clicked);
    18. stopTorunning->setTargetState(running);
    19. connect(stopTorunning, SIGNAL(triggered()), this, SLOT(stopToRunningSlot()));
    20. stop->addTransition(stopTorunning);
    21. //running->addTransition(ui->changeStateButton, &QPushButton::clicked, pause);
    22. QSignalTransition *runningTopause = new QSignalTransition(ui->changeStateButton, &QPushButton::clicked);
    23. runningTopause->setTargetState(pause);
    24. connect(runningTopause, SIGNAL(triggered()), this, SLOT(runningToPauseSlot()));
    25. running->addTransition(runningTopause);
    26. //pause->addTransition(ui->changeStateButton, &QPushButton::clicked, running);
    27. QSignalTransition *pauseTorunning = new QSignalTransition(ui->changeStateButton, &QPushButton::clicked);
    28. pauseTorunning->setTargetState(running);
    29. connect(pauseTorunning, SIGNAL(triggered()), this, SLOT(pauseToRunningSlot()));
    30. pause->addTransition(pauseTorunning);
    31. //running->addTransition(ui->resumeButton, SIGNAL(clicked()), stop);
    32. QSignalTransition *runningTostop = new QSignalTransition(ui->resumeButton, &QPushButton::clicked);
    33. runningTostop->setTargetState(stop);
    34. connect(runningTostop, SIGNAL(triggered()), this, SLOT(runningToStopSlot()));
    35. running->addTransition(runningTostop);
    36. //pause->addTransition(ui->resumeButton, SIGNAL(clicked()), stop);
    37. QSignalTransition *pauseTostop = new QSignalTransition(ui->resumeButton, &QPushButton::clicked);
    38. pauseTostop->setTargetState(stop);
    39. connect(pauseTostop, SIGNAL(triggered()), this, SLOT(pauseToStopSlot()));
    40. pause->addTransition(pauseTostop);
    41. machine.start();
    42. stop->assignProperty(ui->stateLabel, "text", QString(tr("停止状态")));
    43. running->assignProperty(ui->stateLabel, "text", QString(tr("运行状态")));
    44. pause->assignProperty(ui->stateLabel, "text", QString(tr("暂停状态")));
    45. }
    46. Widget::~Widget()
    47. {
    48. delete ui;
    49. }
    50. void Widget::stopToRunningSlot()
    51. {
    52. ui->textBrowser->append(QString("停止到运行"));
    53. }
    54. void Widget::runningToPauseSlot()
    55. {
    56. ui->textBrowser->append(QString("运行到暂停"));
    57. }
    58. void Widget::pauseToRunningSlot()
    59. {
    60. ui->textBrowser->append(QString("暂停到运行"));
    61. }
    62. void Widget::runningToStopSlot()
    63. {
    64. ui->textBrowser->append(QString("运行到停止"));
    65. }
    66. void Widget::pauseToStopSlot()
    67. {
    68. ui->textBrowser->append(QString("暂停到停止"));
    69. }

  • 相关阅读:
    基于Matlab求解高教社杯数学建模竞赛(cumcm2010A题)-储油罐的变位识别与罐容表标定(附上源码+数据+题目)
    Spring Security 注册过滤器关键点与最佳实践
    linux 离线安装软件
    二分查找算法介绍(边界值、循环条件、值的变化、二分查找的原理、异常处理)
    【超级详细的Vue安装与配置教程】
    生产环境p0级故障:用户钱付了,订单还是显示未支付,用户把我们投诉了!
    ThreadPoolExecutor源码分析
    R数据分析:扫盲贴,什么是多重插补
    SSM+智慧养老服务平台 毕业设计-附源码211709
    STC15单片机-按键检测单击、双击和长按(状态机)
  • 原文地址:https://blog.csdn.net/gdizcm/article/details/128125681