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
Qt 在修改更改相关项目信息的文本框(QLineEdit)时,如何避免无限循环?_Qt_Textbox_Infinite Loop - Fatal编程技术网

Qt 在修改更改相关项目信息的文本框(QLineEdit)时,如何避免无限循环?

Qt 在修改更改相关项目信息的文本框(QLineEdit)时,如何避免无限循环?,qt,textbox,infinite-loop,Qt,Textbox,Infinite Loop,我在一个小部件中有几个字段,每个字段都会影响一个项目的行为,更改其中一些字段会更改其他字段 我在某处读到,行编辑的editingFinished()信号仅由用户操作触发,而不是由代码更改触发。。。这是真的吗 connect(m_lineEdit1, SIGNAL(editingFinished()), this, SLOT(m_lineEdit1Changed())); connect(m_lineEdit2, SIGNAL(editingFinished()), this, SLOT(m_li

我在一个小部件中有几个字段,每个字段都会影响一个项目的行为,更改其中一些字段会更改其他字段

我在某处读到,行编辑的
editingFinished()
信号仅由用户操作触发,而不是由代码更改触发。。。这是真的吗

connect(m_lineEdit1, SIGNAL(editingFinished()), this, SLOT(m_lineEdit1Changed()));
connect(m_lineEdit2, SIGNAL(editingFinished()), this, SLOT(m_lineEdit2Changed()));

connect(this, SIGNAL(someSignal()), this, SLOT(updateData()));

void m_lineEdit1Changed()
{
    changedata1();
    emit someSignal();
}

void m_lineEdit2Changed()
{
    changedata2();
    emit someSignal();
}

void updateData()
{
    m_lineEdit1.setText(fromdata);
    m_lineEdit2.setText(fromdata);
}
如果我更改
m_lineEdit1
,并更新整个小部件(通过代码
m_lineEdit2
),我会在
m_lineEdit2Changed()

这将导致无限的更新循环


我能做些什么来避免这个问题?

避免这个问题的一种方法是使用这个函数

在您的示例中,您将执行以下操作:

void updateData()
{
    m_lineEdit1.blockSignals(true);
    m_lineEdit1.setText(fromdata);
    m_lineEdit1.setText(fromdata);
    m_lineEdit1.blockSignals(false);
}

blockSignals()调用阻止对象在您更改行编辑中的数据时发送任何信号。

阻塞信号有点像是一种方法的重锤。您可以使用sentinel类显式防止递归:

#define SENTINEL_STRINGIFY(x) #x
#define SENTINEL_TOSTRING(x) SENTINEL_STRINGIFY(x)
#define SENTINEL_AT __FILE__ ":" SENTINEL_TOSTRING(__LINE__)

class Sentinel {
  Q_DISABLE_COPY(Sentinel);
  static QMutex m_mutex;
  static QSet<QString> m_sentinels;
  QString const m_sentinel;
  bool const m_ok;
  static bool checkAndSet(const QString & sentinel) {
    QMutexLocker lock(&m_mutex);
    if (m_sentinels.contains(sentinel)) return false;
    m_sentinels.insert(sentinel);
    return true;
  }

public:
  explicit Sentinel(const char * sentinel) :
    m_sentinel(sentinel), m_ok(checkAndSet(m_sentinel)) {}
  ~Sentinel() { 
    if (!m_ok) return;
    QMutexLocker lock(&m_mutex);
    m_sentinels.remove(m_sentinel);
  }
  bool operator()() const { return m_ok; }
};
QMutex Sentinel::m_mutex;
QSet<QString> Sentinel::m_sentinels;

...
void Foo::m_lineEdit1Changed()
{
  Sentinel s(SENTINEL_AT);
  if (!s) return; // exit if this method is on the call stack
  ...
  changedata1();
  emit someSignal();
}
#定义SENTINEL_STRINGIFY(x)#x
#定义SENTINEL_-TOSTRING(x)SENTINEL_-STRINGIFY(x)
#在文件中定义哨兵“:“哨兵”到字符串(uuu行)
班哨{
Q_禁用_复制(Sentinel);
静态qmutexm_互斥体;
静态QSet m_哨兵;
QString const m_sentinel;
布尔常数m_ok;
静态布尔校验集(常量QString和sentinel){
QMutexLocker锁(&m_互斥锁);
如果(m_sentinels.contains(sentinel))返回false;
m_sentinel.插入(sentinel);
返回true;
}
公众:
显式Sentinel(常量字符*Sentinel):
m_sentinel(sentinel),m_ok(checkAndSet(m_sentinel)){}
~Sentinel(){
如果(!m_ok)返回;
QMutexLocker锁(&m_互斥锁);
m_sentinel.移除(m_sentinel);
}
布尔运算符()()常量{return m_ok;}
};
QMutex Sentinel::m_互斥体;
QSet哨兵:m_哨兵;
...
void Foo::m_lineEdit1Changed()
{
哨兵s(哨兵AT);
if(!s)return;//如果此方法位于调用堆栈上,则退出
...
changedata1();
发出某种信号();
}

这是线程安全的,可以从任何线程使用。

这是Qt在5.3中引入的
QSignalBlocker
类的一种非常常见的技术,它克服了上述手动方式的一些缺陷。