你上面使用的状态机与你所描述的不相符。使用最终状态是不正确的,因为在输入大于零的值后,我没有看到任何阻止用户再次输入零的东西。因此,有效状态不能是最终状态。从你的代码中可以看出,用户可以以任何顺序更改窗口小部件的状态。你的状态机必须注意这一点。
我将使用一个具有四个子状态的状态机(无有效输入,一个有效输入,两个有效输入,三个有效输入)。显然,你从无效输入开始。每个窗口小部件都可以从无到一个并返回(同样适用于两个和三个)。当输入三个时,所有窗口小部件都是有效的(按钮启用)。对于所有其他状态,在进入状态时必须禁用按钮。
我写了一个示例应用程序。主窗口包含两个QCheckBoxes、一个QSpinBox和一个QPushButton。主窗口中有信号,记录状态的转换。当窗口小部件的状态发生变化时,它们会被触发。
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
bool m_editValid;
bool isEditValid() const;
void setEditValid(bool value);
private slots:
void on_checkBox1_stateChanged(int state);
void on_checkBox2_stateChanged(int state);
void on_spinBox_valueChanged (int i);
signals:
void checkBox1Checked();
void checkBox1Unchecked();
void checkBox2Checked();
void checkBox2Unchecked();
void editValid();
void editInvalid();
};
#endif
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), m_editValid(false)
{
ui->setupUi(this);
QStateMachine* stateMachine = new QStateMachine(this);
QState* noneValid = new QState(stateMachine);
QState* oneValid = new QState(stateMachine);
QState* twoValid = new QState(stateMachine);
QState* threeValid = new QState(stateMachine);
noneValid->addTransition(this, SIGNAL(checkBox1Checked()), oneValid);
oneValid->addTransition(this, SIGNAL(checkBox1Checked()), twoValid);
twoValid->addTransition(this, SIGNAL(checkBox1Checked()), threeValid);
threeValid->addTransition(this, SIGNAL(checkBox1Unchecked()), twoValid);
twoValid->addTransition(this, SIGNAL(checkBox1Unchecked()), oneValid);
oneValid->addTransition(this, SIGNAL(checkBox1Unchecked()), noneValid);
noneValid->addTransition(this, SIGNAL(checkBox2Checked()), oneValid);
oneValid->addTransition(this, SIGNAL(checkBox2Checked()), twoValid);
twoValid->addTransition(this, SIGNAL(checkBox2Checked()), threeValid);
threeValid->addTransition(this, SIGNAL(checkBox2Unchecked()), twoValid);
twoValid->addTransition(this, SIGNAL(checkBox2Unchecked()), oneValid);
oneValid->addTransition(this, SIGNAL(checkBox2Unchecked()), noneValid);
noneValid->addTransition(this, SIGNAL(editValid()), oneValid);
oneValid->addTransition(this, SIGNAL(editValid()), twoValid);
twoValid->addTransition(this, SIGNAL(editValid()), threeValid);
threeValid->addTransition(this, SIGNAL(editInvalid()), twoValid);
twoValid->addTransition(this, SIGNAL(editInvalid()), oneValid);
oneValid->addTransition(this, SIGNAL(editInvalid()), noneValid);
threeValid->assignProperty(ui->pushButton, "enabled", true);
twoValid->assignProperty(ui->pushButton, "enabled", false);
oneValid->assignProperty(ui->pushButton, "enabled", false);
noneValid->assignProperty(ui->pushButton, "enabled", false);
stateMachine->setInitialState(noneValid);
stateMachine->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::isEditValid() const
{
return m_editValid;
}
void MainWindow::setEditValid(bool value)
{
if (value == m_editValid)
{
return;
}
m_editValid = value;
if (value)
{
emit editValid();
} else {
emit editInvalid();
}
}
void MainWindow::on_checkBox1_stateChanged(int state)
{
if (state == Qt::Checked)
{
emit checkBox1Checked();
} else {
emit checkBox1Unchecked();
}
}
void MainWindow::on_checkBox2_stateChanged(int state)
{
if (state == Qt::Checked)
{
emit checkBox2Checked();
} else {
emit checkBox2Unchecked();
}
}
void MainWindow::on_spinBox_valueChanged (int i)
{
setEditValid(i > 0);
}
这应该可以解决问题。正如您自己已经提到的,有更好的方法来实现此行为。特别是跟踪状态之间的所有转换容易出错。