Конечный автомат, который вы использовали выше, не соответствует описанному вами. Использование конечного состояния некорректно, потому что после ввода значения больше нуля я не вижу ничего, что мешало бы пользователю снова ввести ноль. Поэтому действительные состояния не могут быть окончательными. Насколько я вижу из вашего кода, пользователю разрешено изменять состояние виджетов в любом порядке. Ваш конечный автомат должен обратить на это внимание.
Я бы использовал конечный автомат с четырьмя дочерними состояниями (без действительного ввода, одного действительного ввода, двух допустимых входов, трех допустимых входов). Вы, очевидно, начнете без правильного ввода. Каждый виджет может сделать переход от одного к одному назад (одинаковое количество для двух и трех). При вводе трех все виджеты действительны (кнопка включена). Для всех остальных состояний кнопка должна быть отключена при входе в состояние.
Я написал пример приложения. Главное окно содержит два 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_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);
}
Это должно сработать. Как вы уже упоминали, есть лучшие способы добиться такого поведения. Особенно следите за всеми переходами между состояниями, склонными к ошибкам.