使用QCoreApplication时,QStateMachine未正确执行
QStateMachine not executing correctly when using QCoreApplication
我正试图在控制台应用程序中实现一个简单的状态机。本应触发状态转换的信号正在发出,然而,状态机并没有对这些信号做出反应。
当在QApplication(即GUI应用程序)中运行时,这个状态机可以完美地工作,但是我想开发一个控制台应用程序。我怀疑我实现事件循环的方式有问题,因为QStateMachine没有发出started()信号。
为了使状态机正常工作,执行应用程序的正确方式是什么?
main.cpp:
#include <QCoreApplication>
#include "test.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Test test;
QMetaObject::invokeMethod( &test, "Run", Qt::QueuedConnection );
return a.exec();
}
test.h:
#ifndef TEST_H
#define TEST_H
#include <QObject>
#include <QStateMachine>
class Test : public QObject
{
Q_OBJECT
public:
explicit Test(QObject *parent = 0) : QObject(parent) {}
public slots:
void Run();
signals:
void stateChanged();
void debugSignal();
private:
void buildStateMachine();
QStateMachine machine;
private slots:
void runS1();
void runS2();
void runS3();
void debugSlot();
};
#endif // TEST_H
test.cpp:
#include "test.h"
#include <QDebug>
void Test::Run()
{
buildStateMachine();
QTextStream qin(stdin);
while (true)
{
QString line = qin.readLine();
qDebug() << "line: " << line;
if (line == "A")
{
qDebug() << "emit stateChanged signal";
emit stateChanged();
}
else if (line == "B")
{
qDebug() << "emit debugSignal";
emit debugSignal();
}
}
}
void Test::buildStateMachine()
{
connect(&machine, SIGNAL(started()), this, SLOT(debugSlot())); // doesn't seem to get triggered... (why is machine not starting?)
connect(this, SIGNAL(debugSignal()), this, SLOT(debugSlot())); // works as expected
QState *s1 = new QState(&machine);
QState *s2 = new QState(&machine);
QState *s3 = new QState(&machine);
s1->addTransition(this, SIGNAL(stateChanged()), s2);
s2->addTransition(this, SIGNAL(stateChanged()), s3);
s3->addTransition(this, SIGNAL(stateChanged()), s1);
connect(s1, SIGNAL(entered()), this, SLOT(runS1())); // these are never triggered
connect(s2, SIGNAL(entered()), this, SLOT(runS2()));
connect(s3, SIGNAL(entered()), this, SLOT(runS3()));
s1->assignProperty(&machine, "state", 1);
s2->assignProperty(&machine, "state", 2);
s3->assignProperty(&machine, "state", 3);
machine.setInitialState(s1);
machine.start();
}
void Test::runS1()
{
qDebug() << "entered state S1";
}
void Test::runS2()
{
qDebug() << "entered state S2";
}
void Test::runS3()
{
qDebug() << "entered state S3";
}
void Test::debugSlot()
{
qDebug() << "slot was triggered!";
}
解决了我的问题。该问题是由while循环无限引起的。只有在Run函数结束后才能调用slot,这显然从未发生过。
这是一个有效的解决方案。对Qt 5风格的信号和插槽语法的更改是可选的。如果main.cpp与上面问题中显示的版本保持原样,则应用程序将无法正确退出。
main.cpp:
#include <QCoreApplication>
#include <QTimer>
#include "test.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Test test;
QObject::connect(&test, &Test::finished, &a, &QCoreApplication::quit, Qt::QueuedConnection);
QTimer::singleShot(0, &test, &Test::Run);
return a.exec();
}
test.h:
#ifndef TEST_H
#define TEST_H
#include <QObject>
#include <QStateMachine>
class Test : public QObject
{
Q_OBJECT
public:
explicit Test(QObject *parent = 0);
signals:
void next_state();
void finished();
private:
void buildStateMachine();
QStateMachine machine;
public slots:
void Run();
void runS1();
void runS2();
void runS3();
void debugSlot();
};
#endif // TEST_H
test.cpp:
#include "test.h"
#include <iostream>
#include <QTextStream>
Test::Test(QObject * parent) : QObject(parent)
{
buildStateMachine();
}
void Test::Run()
{
QTextStream qin(stdin);
std::cout << "line: ";
QString line = qin.readLine();
if (line == "A")
{
std::cout << "emit stateChanged signal" << std::endl;
emit next_state();
}
else if (line == "q")
{
emit finished();
}
else
{
Run();
}
}
void Test::buildStateMachine()
{
QState *s1 = new QState(&machine);
QState *s2 = new QState(&machine);
QState *s3 = new QState(&machine);
s1->addTransition(this, SIGNAL(next_state()), s2);
s2->addTransition(this, SIGNAL(next_state()), s3);
s3->addTransition(this, SIGNAL(next_state()), s1);
connect(s1, &QState::entered, this, &Test::runS1);
connect(s2, &QState::entered, this, &Test::runS2);
connect(s3, &QState::entered, this, &Test::runS3);
machine.setInitialState(s1);
machine.start();
}
void Test::runS1()
{
std::cout << "entered state S1" << std::endl;
Run();
}
void Test::runS2()
{
std::cout << "entered state S2" << std::endl;
Run();
}
void Test::runS3()
{
std::cout << "entered state S3" << std::endl;
Run();
}
void Test::debugSlot()
{
std::cout << "debug slot was triggered!" << std::endl;
Run();
}
相关文章:
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- C++,系统无法执行指定的程序
- 使用C++中的模板和运算符重载执行矩阵运算
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 执行函数时导致崩溃的变量
- 无论条件是否为true,if总是在c++中执行
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 在C++中对T*类型执行std::move的意外行为
- 使用QProcess执行命令,并将结果存储在QStringList中
- 如何在没有信号的情况下从C++执行QML插槽
- 如何确认我的constexpr表达式实际上已经在编译时执行
- C++17中的并行执行策略
- QML按钮点击功能执行顺序
- 程序在执行程序的其余部分之前退出
- 为什么catch中的代码没有被执行
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 将执行、作业和WinAPI相乘
- 对字符数组中的元素执行逐位操作
- 为什么g++在未执行的代码处标记强制转换错误
- 使用QCoreApplication时,QStateMachine未正确执行