2014-04-03 52 views
2

是否有任何方法检查对话框的UI元素(行编辑,组合框等)是否已更改。检查UI元素的值是否已更改

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

我可以做的是使用连接为每个UI元素&根据每个元素的值更改我设置一个布尔标志&在关闭事件时我正在检查该布尔标志。
但它相当复杂的检查每个部件。 有没有更简单的方法。 代码,我使用了单个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(); 
    } 
} 

回答

0

如果你只检查是否在对话框关闭输入字段填写,你不需要标志只能检查是否有任何输入。

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

从您发布的代码,我不能真正看到你需要的标志。

+0

如果假设有在我的对话框20至30的UI元素,然后通过检查每个输入,这将是一个巨大的没有。的比较,这肯定是不可靠的。 – krohit

+0

那么每个人都有一个更好的标志? – Bowdzone

2

您无法重新实现closeEvent以防止关闭窗口。由于closeEvent方法调用只是通知即将结束的一种方式,因此您所做的呼叫是冗余或错误(无限递归)。在这一点上,要做任何事情都为时已晚。

请记住以下几点:

  1. 关闭对话框通常等同于撤销对话框。只有单击确定应该接受更改。

  2. 当用户想要关闭对话框时,不必向他们询问。他们发起了行动。但是:

  3. 是适当的询问用户关于对话框关闭,如果有变化不是接受 - 上比OS X.

所以其他平台上,你所要做的几件事情:

  1. 重新实现void event(QEvent*)方法。这允许您拒绝关闭事件。

  2. 优惠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,并将其连接到设置标志的函数。


要确定更改的字段,您不一定需要标志。在许多对话框中,有一个表示对话框中的数据的数据结构是有意义的。然后,您可以使用getset方法从对话框中检索数据,或将其设置在对话框中。要检查更改的数据,只需将原始数据比较当前数据:

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

感谢您的回复它真的有帮助,现在我正在使用每个部件的foreach循环(即QLineEdit,QTextEdit,QComboBox,QDateEdit)。但是有没有其他方式直接检查小部件(foreach循环for QWidget),它们是可修改的(即因为使用单个foreach循环可以很容易)。 – krohit

+0

你可以解释一下如何使用QMetaObject?像例子..... – krohit

+0

@RohitKKK看到编辑。 –

相关问题