Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt 检查ui元素的值是否已更改_Qt_Connect_Qdialog_Selectionchanged_Textchanged - Fatal编程技术网

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

Qt 检查ui元素的值是否已更改,qt,connect,qdialog,selectionchanged,textchanged,Qt,Connect,Qdialog,Selectionchanged,Textchanged,是否有办法检查对话框的ui元素(行编辑、组合框等)是否已更改 我想要的是,如果用户更改了任何单个ui元素的值,就向用户显示一条消息,说明细节已经部分填充 我能做的是为每个ui元素使用connect&根据每个元素的值更改,我设置一个布尔标志&在关闭事件时,我检查该布尔标志。 但是为每个小部件检查它是相当复杂的。 有没有更简单的办法。 我用于单个ui元素的代码是 connect(ui->leAge,SIGNAL(textChanged(QString)),this,SLOT(functChan

是否有办法检查对话框的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();
   }
}

如果只在对话框关闭时检查输入字段是否已填充,则不需要标记,只需检查是否有输入即可

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


从你发布的代码中,我看不出你需要这些标志做什么。

你不能重新实现
closeEvent
来阻止关闭窗口。您执行的
close()
调用要么是冗余的,要么是错误的(无限递归),因为
closeEvent
方法调用只是通知即将关闭的一种方式。到那时,做任何事都为时已晚

请记住以下几点:

  • 关闭对话框通常相当于取消对话框。只有单击“确定”才能接受更改

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

  • 在OSX以外的平台上,如果有未被接受的更改,可以询问用户有关对话框关闭的问题

  • 因此,你必须做几件事:

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

  • 提供应用/重置/取消按钮


  • 您的标志方法可以自动化。您可以找到对话框的所有控件并自动设置连接。对每种类型的控件重复以下语句-这很快就会变得单调乏味:

    foreach(QTextEdit* w, findChildren<QTextEdit*>())
      connect(w, SIGNAL(textChanged(QString)), SLOT(functChanged()));
    
    每个小部件都是一个
    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元素,那么通过检查每个输入,这将是一个巨大的比较数量,这肯定是不可靠的。那么为每个元素设置一个标志是否更好呢?感谢您的回复,它确实很有帮助,现在我为每个小部件使用foreach循环(即QLineEdit、QTextEdit、QComboBox、QDateEdit)。但是有没有其他方法可以直接检查可修改的小部件(QWidget的foreach循环)(也就是说,因为使用单个foreach循环很容易)。
    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); }
    };