上で使用したステート マシンは、説明したものと一致しません。ゼロより大きい値を入力した後、ユーザーが再びゼロを入力するのを妨げるものは何も表示されないため、最終状態の使用は正しくありません。したがって、有効な状態を最終的なものにすることはできません。コードからわかる限り、ユーザーはウィジェットの状態を任意の順序で変更できます。ステート マシンはこれに注意を払う必要があります。
4 つの子ステート (有効な入力なし、1 つの有効な入力、2 つの有効な入力、3 つの有効な入力) を持つステート マシンを使用します。明らかに、有効な入力なしで開始します。各ウィジェットは、「いいえ」から「1 つ戻る」への遷移を行うことができます (2 つと 3 つでも同じカウント)。3 つ入力すると、すべてのウィジェットが有効になります (ボタンが有効になります)。他のすべての状態では、状態に入ったときにボタンを無効にする必要があります。
サンプルアプリを書きました。メイン ウィンドウには、QSpinBox と QPushButton の 2 つの QCheckBox があります。メインウィンドウには信号があり、状態の遷移を簡単に書き留めることができます。ウィジェットの状態が変更されたときに発生します。
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_H
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);
}
これでうまくいくはずです。あなた自身がすでに述べたように、この動作を達成するためのより良い方法があります。特に、状態間のすべての遷移を追跡すると、エラーが発生しやすくなります。