您无法重新实现closeEvent
以防止关闭窗口。由于closeEvent
方法调用只是通知即将结束的一种方式,因此您所做的呼叫是冗余或错误(无限递归)。在这一点上,要做任何事情都为时已晚。
请记住以下几点:
关闭对话框通常等同于撤销对话框。只有单击确定应该接受更改。
当用户想要关闭对话框时,不必向他们询问。他们发起了行动。但是:
是适当的询问用户关于对话框关闭,如果有变化不是接受 - 上比OS X.
所以其他平台上,你所要做的几件事情:
重新实现void event(QEvent*)
方法。这允许您拒绝关闭事件。
优惠Apply/Reset/Cancel
按钮。
你的标志方式可以实现自动化。您可以找到对话框的所有控件并自动设置连接。重复的语句下面每一种类型的控制 - 这相当快地变得乏味:
foreach(QTextEdit* w, findChildren<QTextEdit*>())
connect(w, SIGNAL(textChanged(QString)), SLOT(functChanged()));
您可以利用元属性系统。大多数控件都具有user
属性 - 这是保存控件的主要值(如文本,选定项目等)的属性。您可以扫描所有的控件的孩子,以及用户属性的属性更改通知信号连接到您的标志:
QMetaMethod slot = metaObject().method(
metaObject().indexOfSlot("functChanged()"));
foreach (QWidget* w, findChildren<QWidget*>()) {
QMetaObject mo = w->metaObject();
if (!mo.userProperty().isValid() || !mo.userProperty().hasNotifySignal())
continue;
connect(w, mo.notifySignal(), this, slot);
}
每个小部件是一个QObject
。 QObject可以有属性,其中一个属性可以声明为用户属性。大多数可编辑的窗口小部件控件都有这样的属性,它表示用户输入(文本,数字值,项目的选定索引等)。通常这样的属性也具有更改通知信号。因此,你所做的只是获得表示通知信号的QMetaMethod
,并将其连接到设置标志的函数。
要确定更改的字段,您不一定需要标志。在许多对话框中,有一个表示对话框中的数据的数据结构是有意义的。然后,您可以使用get
和set
方法从对话框中检索数据,或将其设置在对话框中。要检查更改的数据,只需将原始数据比较当前数据:
struct UserData {
QString name;
int age;
UserData(const QString & name_, int age_) :
name(name_), age(age_) {}
UserData() {}
};
class DialogBase : public QDialog {
QDialogButtonBox m_box;
protected:
QDialogButtonBox & buttonBox() { return m_box; }
virtual void isAccepted() {}
virtual void isApplied() {}
virtual void isReset() {}
virtual void isRejected() {}
public:
DialogBase(QWidget * parent = 0) : QDialog(parent) {
m_box.addButton(QDialogButtonBox::Apply);
m_box.addButton(QDialogButtonBox::Reset);
m_box.addButton(QDialogButtonBox::Cancel);
m_box.addButton(QDialogButtonBox::Ok);
connect(&m_box, SIGNAL(accepted()), SLOT(accept()));
connect(&m_box, SIGNAL(rejected()), SLOT(reject()));
connect(this, &QDialog::accepted, []{ isAccepted(); });
connect(this, &QDialog::rejected, []{ isRejected(); });
connect(&buttonBox(), &QDialogButtonBox::clicked, [this](QAbstractButton* btn){
if (m_box.buttonRole(btn) == QDialogButtonBox::ApplyRole)
isApplied();
else if (m_box.buttonRole(btn) == QDialogButtonBox::ResetRole)
isReset();
});
}
}
class UserDialog : public DialogBase {
QFormLayout m_layout;
QLineEdit m_name;
QSpinBox m_age;
UserData m_initialData;
public:
UserDialog(QWidget * parent = 0) : QDialog(parent), m_layout(this) {
m_layout.addRow("Name", &m_name);
m_layout.addRow("Age", &m_age);
m_age.setRange(0, 200);
m_layout.addRow(&buttonBox());
}
/// Used by external objects to be notified that the settings
/// have changed and should be immediately put in effect.
/// This signal is emitted when the data was changed.
Q_SIGNAL void applied(UserData const &);
UserData get() const {
return UserData(
m_name.text(), m_age.value());
}
void set(const UserData & data) {
m_name.setText(data.name);
m_age.setValue(data.age);
}
void setInitial(const UserData & data) { m_initialData = data; }
bool isModified() const { return get() == m_initialData; }
protected:
void isAccepted() Q_DECL_OVERRIDE { emit applied(get()); }
void isApplied() Q_DECL_OVERRIDE { emit applied(get()); }
void isReset() Q_DECL_OVERRIDE { set(m_initialData); }
};
如果假设有在我的对话框20至30的UI元素,然后通过检查每个输入,这将是一个巨大的没有。的比较,这肯定是不可靠的。 – krohit
那么每个人都有一个更好的标志? – Bowdzone