Qt利用QState状态机实现控件互斥操作详解

 更新时间:2022年12月05日 14:09:03   作者:中国好公民st  
这篇文章主要为大家详细介绍了Qt如何利用QState状态机实现控件互斥操作,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

最近学习了QState状态机功能,今天为大家分享下如何实现按钮的互斥效果吧。

首先,看一下实现效果~

功能讲解

开发环境:VS2017 + Qt5.14.2

该例子实现了类似于QRadioButton的效果。

从QtDesigner中拖出了三个QPushButton控件,分别是:ui.btn1、ui.btn2、ui.btn3,每个按钮都有对应的状态,分别是:state1、state2、state3

选中后背景颜色值是:QColor(255,182,193)、未选中的背景颜色值是:QColor(255,239,213);

设置步骤

1:设置btn1对应的状态信息

QState *state1 = new QState;
state1->assignProperty(ui.btn1, "text", QStringLiteral("1选中"));
state1->assignProperty(ui.btn1, "styleSheet", "background-color:rgb(255,182,193)");
state1->assignProperty(ui.btn2, "text", QStringLiteral("2"));
state1->assignProperty(ui.btn2, "styleSheet", "background-color:rgb(255,239,213)");
state1->assignProperty(ui.btn3, "text", QStringLiteral("3"));
state1->assignProperty(ui.btn3, "styleSheet", "background-color:rgb(255,239,213)");

代码讲解使用QState::assignProperty,指示此状态在进入状态时将具有给定对象的给定名称的属性设置为给定值。

通俗来说,就是响应状态需要让哪些按钮做什么样的操作。

在响应state1状态时,btn1的文字变成了"1选中",背景颜色也发生了变化,同理,state2、state3也是如此。

2:设置btn2对应的状态信息

QState *state2 = new QState;
state2->assignProperty(ui.btn1, "text", QStringLiteral("1"));
state2->assignProperty(ui.btn1, "styleSheet", "background-color:rgb(255,239,213)");
state2->assignProperty(ui.btn2, "text", QStringLiteral("2选中"));
state2->assignProperty(ui.btn2, "styleSheet", "background-color:rgb(255,182,193)");
state2->assignProperty(ui.btn3, "text", QStringLiteral("3"));
state2->assignProperty(ui.btn3, "styleSheet", "background-color:rgb(255,239,213)");

3:设置btn3对应的状态信息

QState *state3 = new QState;
state3->assignProperty(ui.btn1, "text", QStringLiteral("1"));
state3->assignProperty(ui.btn1, "styleSheet", "background-color:rgb(255,239,213)");
state3->assignProperty(ui.btn2, "text", QStringLiteral("2"));
state3->assignProperty(ui.btn2, "styleSheet", "background-color:rgb(255,239,213)");
state3->assignProperty(ui.btn3, "text", QStringLiteral("3选中"));
state3->assignProperty(ui.btn3, "styleSheet", "background-color:rgb(255,182,193)");

4:设置停止状态

当设置了所有控件对应的状态后,最后需要设置停止状态。停止状态是一个单独的状态类:QFinalState。

QFinalState *stateFinal = new QFinalState;

5:数据绑定

每个单独的状态设置完成后,那么该如何对状态以及按钮做绑定呢?

state1->addTransition(ui.btn1, &QPushButton::clicked, state1);
state2->addTransition(ui.btn2, &QPushButton::clicked, state2);
state3->addTransition(ui.btn3, &QPushButton::clicked, state3);

6:将所有的状态添加到状态机QStateMachine中

QStateMachine *pMachine = new QStateMachine;
pMachine->addState(state1);
pMachine->addState(state2);
pMachine->addState(state3);
pMachine->addState(stateFinal);

7:设置初始化状态

上述工作完成后,必须要给状态机设置初始状态,并且状态必须是这个状态的子状态。

pMachine->setInitialState(state1);

8:开始运行状态

pMachine->start();

好了,根据上述代码,进行调试运行试试?

结果发现,无论点击哪个按钮,按钮都没有反应,原因出到哪里呢?

答:错误是出在了第5步,当前状态是无法绑定自己的,那么该如何实现这种互斥?

对需要进行控件绑定的状态:stat1、state2、state3,设置一个父状态,由父状态来分配数据绑定就可以实现啦。

修改方案

1:创建父状态

QState *stateParent = new QState;

2:每个状态设置父状态

对state1、state2、state3的构造函数中,分别继承自stateParent,修改如下:

QState *state1 = new QState(stateParent);
QState *state2 = new QState(stateParent);
QState *state3 = new QState(stateParent);

3:数据绑定修改

由父状态进行分配状态对应,修改如下:

stateParent->addTransition(ui.btn1, &QPushButton::clicked, state1);
stateParent->addTransition(ui.btn2, &QPushButton::clicked, state2);
stateParent->addTransition(ui.btn3, &QPushButton::clicked, state3);
QFinalState *stateFinal = new QFinalState(stateParent);

并且,初始化父状态的初始子状态

stateParent->setInitialState(state1);

4:状态机数据绑定

此时,不需要将state1、state2、state3直接绑定到pMachine中了,而是将stateParent绑定到pMachine中。

并且,设置状态机pMachine的初始状态是stateParent。

经过如此修改后,调试代码发现,可以实现按钮的互斥效果了,也就是文章开始的动画效果。

在不使用状态时,使用stateFinal进行销毁就可以了。比如在响应关闭按钮时,可以做结束处理

stateParent->addTransition(ui.btnExit, &QPushButton::clicked, stateFinal);

下面贴出完整代码

今日份分享就到这里了~

到此这篇关于Qt利用QState状态机实现控件互斥操作详解的文章就介绍到这了,更多相关Qt控件互斥操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • 结构体对齐的规则详解及C++代码验证

    结构体对齐的规则详解及C++代码验证

    在c语言的结构体里面一般会按照某种规则去进行字节对齐。本文就来介绍一下如何实现,具有一定的参考价值,感兴趣的可以了解下
    2021-08-08
  • Qt模仿Visual Studio停靠窗口效果

    Qt模仿Visual Studio停靠窗口效果

    这篇文章主要介绍了如何利用Qt制作与Visual Studio相似的带有停靠方向标及停靠区域预览的停靠窗口框架,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2022-01-01
  • C++实例分析讲解临时对象与右值引用的用法

    C++实例分析讲解临时对象与右值引用的用法

    对性能来说,许多的问题都需要和出现频率及本身执行一次的开销挂钩,有些问题虽然看似比较开销较大,但是很少会执行到,那也不会对程序有大的影响;同样一个很小开销的函数执行很频繁,同样会对程序的执行效率有很大影响。本章中作者主要根据临时对象来阐述这样一个观点
    2022-08-08
  • win32使用openfilename浏览文件窗口示例

    win32使用openfilename浏览文件窗口示例

    这篇文章主要介绍了使用win32 API打开浏览文件窗口,使用OPENFILENAME结构体来实现这个功能,需要的朋友可以参考下
    2014-02-02
  • 使用C语言实现交换整数的奇数位和偶数位

    使用C语言实现交换整数的奇数位和偶数位

    在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使用C语言代码实现将一个整数的奇数位和偶数位交换,需要的朋友可以参考下
    2025-03-03
  • C++ std:map的使用方法

    C++ std:map的使用方法

    std::map是C++标准库中一个强大而高效的关联容器,本文就来介绍一下C++ std:map的使用方法,具有一定的参考价值,感兴趣的可以了解一下
    2025-02-02
  • 深入理解c语言数组

    深入理解c语言数组

    这篇文章主要介绍了c语言数组,有需要的朋友可以参考一下
    2013-12-12
  • C语言入门篇--关键字static详解

    C语言入门篇--关键字static详解

    本篇文章是C语言系列基础篇,C语言中,static是用来修饰变量和函数:1.修饰局部变量–>静态局部变量2.修饰全局变量–>静态全局变量3.修饰函数–>静态函数
    2021-08-08
  • C++实现飞机大战

    C++实现飞机大战

    这篇文章主要为大家详细介绍了C++实现飞机大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • C++实现词法分析器

    C++实现词法分析器

    这篇文章主要为大家详细介绍了C++实现词法分析器的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01

最新评论