明确设置值时抑制Qt信号的正确方法是啥

Posted

技术标签:

【中文标题】明确设置值时抑制Qt信号的正确方法是啥【英文标题】:What is the right way to suppress Qt signals when values are explicitely set明确设置值时抑制Qt信号的正确方法是什么 【发布时间】:2013-04-02 11:00:03 【问题描述】:

我从 QWidget 派生类中获得了一个包含三个 QSpinBox(例如坐标)的派生类。 valueChanged() 信号至少在以下三种情况下被连接并发出:

    上/下按钮 手动输入号码 setValue()

但是,当使用setValue() 时,我想抑制信号,因为我不想拥有(三个)信号。据我了解,有两种方法可以处理:

    QObject::blockSignals() 使用一个标志来指示值是否被明确设置

两种变体都有效,但我认为它们根本不是直截了当的:对于第一个,我通常会阻止所有信号并且我需要为所有底层小部件设置 blockSignals(true)(blockSignals 不会阻止子 QObjects我的应用程序)。对于第二个,我需要在每个更新方法中查询标志,并且虽然我不需要它们,但会引发信号。

是否有任何通用设计模式可以防止此类行为?如果不是,您更喜欢哪种变体?

【问题讨论】:

【参考方案1】:

第三个选项是继承 QSpinBox,在那里实现所需的功能,并使用派生类而不是 QSpinBox - 这隐藏了派生类中所有相关的复杂性,并允许您像使用 QSpinBox 一样使用它。

比如下面的类

myQSpinBox.h

#ifndef MYQSPINBOX_H
#define MYQSPINBOX_H

#include <QSpinBox>

class myQSpinBox : public QSpinBox

    Q_OBJECT
public:
    myQSpinBox(QWidget * parent = 0 );
protected:
    bool valueBeingSet;
public slots:
    void setValue (int val);
private slots:
    void On_valueChanged(int val);
signals:
    void valueChangedNotBySet(int val);
;

#endif // MYQSPINBOX_H

myQSpinBox.cpp

#include "myQSpinBox.h"

myQSpinBox::myQSpinBox(QWidget * parent)
        : QSpinBox(parent)
        , valueBeingSet(false)

    connect(this,SIGNAL(valueChanged(int)),this,SLOT(On_valueChanged(int)));


void    myQSpinBox::setValue ( int val )

    valueBeingSet = true;
    QSpinBox::setValue(val);
    valueBeingSet = false;


void myQSpinBox::On_valueChanged(int val)

    if(!valueBeingSet)
        emit valueChangedNotBySet(val);

将在情况 1. 和 2. 中发出 valueChangedNotBySet(int);,但在情况 3. 中不会发出,保持所有 QSpinBox 功能完整

【讨论】:

嗨,伊利亚,谢谢。你是绝对正确的——这是第三个(也是迄今为止最干净的)变体。但是,我需要重新实现(一次)各种小部件(QSpinBox 只是一个示例) - QLineEdit、QComboBox、QDoubleSpinBox、...。 我不确定是否需要重新实现 QLineEdit - 因为 QLineEdit 有信号 textChanged(const QString & text) 和 textEdited(const QString & text) 允许区分编辑类型。同样可能适用于 QComboBox... 只有当一切都发生在 UI 线程中时才会起作用。当跨多个线程有信号/槽连接链时,valueBeingSet 将在再次(无限)发出valueChnaged 信号之前设置为false,因为事件处理程序将被异步调用。 @mescalinum 是的,此示例假设单个 ui 线程。但是,我认为它可以通过添加 QWaitCondition 成员变量并在 QSpinBox::setValue(val); 之后等待它来轻松适应您描述的场景。在设置 valueBeingSet = false 之前; (从 On_valueChanged 唤醒等待条件)。

以上是关于明确设置值时抑制Qt信号的正确方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

类型擦除成员函数指针的“正确”方法是啥?

QT在这种情况下如何发出信号

Qt信号和槽的问题

使用完成信号退出 Qt 中的线程并进行 clean_up 的正确方法

QT 信号/槽

Qt5:如何在线程中等待信号?