检查ui元素的值是否已更改

问题描述 投票:0回答:2

有什么方法可以检查对话框的 ui 元素(行编辑、组合框等)是否已更改。

我想要的是,如果用户更改任何单个 ui 元素的值,则向用户显示一条消息,说明详细信息已部分填充。

我能做的是对每个 ui 元素使用 connect 并根据每个元素的值更改,我设置一个布尔标志,并在关闭事件时我检查该布尔标志。
但检查每个小部件的情况相当复杂。 有没有更简单的办法。 我用于单个 ui 元素的代码是,

connect(ui->leAge,SIGNAL(textChanged(QString)),this,SLOT(functChanged())); //In Constructor

void DemoDialog::functChanged()   //Will be called if value of line edit (ui->leAge) is changed
{
    flag=true;
}

void DemoDialog::closeEvent(QCloseEvent *event)
{
 if (flag) {
    if (QMessageBox::warning(this,"Close","Do you want to close?",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes) {
        this->close();
   }
}
qt qdialog textchanged selectionchanged
2个回答
3
投票

您无法重新实现

closeEvent
来防止关闭窗口。您所做的
close()
调用要么是多余的,要么是错误(无限递归),因为
closeEvent
方法调用只是“通知”即将关闭的一种方式。到那时再采取任何行动都为时已晚。 请记住以下几点:

    关闭对话框通常相当于取消对话框。只需单击“确定”即可接受更改。
  1. 当用户想要关闭对话框时,您不必询问他们。他们发起了行动。但是:
  2. 如果有更改尚未被
  3. 接受

    ,则应向用户询问对话框关闭问题 - 在 OS X 以外的平台上。

  4. 所以,你必须做几件事:

    重新实现
  1. void event(QEvent*)

    方法。这允许您拒绝关闭事件。

    
    

  2. 提供
  3. 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); } };



0
投票

如果您在某些时候以编程方式填充输入字段,但也只对对话框关闭时的更改感兴趣,您还可以在关闭函数中检查当前输入是否等于您之前设置的输入。

从您发布的代码中,我真的看不出您需要这些标志的用途。

© www.soinside.com 2019 - 2024. All rights reserved.