Qml/QtQuick2 中的 QSignalBlocker?

Posted

技术标签:

【中文标题】Qml/QtQuick2 中的 QSignalBlocker?【英文标题】:QSignalBlocker in Qml/QtQuick2? 【发布时间】:2017-07-17 08:35:51 【问题描述】:

我想在不触发附加信号的情况下动态设置 ComboBox 的 currentIndex。

我目前正在使用 bool 属性来设置一个标志,该标志在我的信号被调用时被清除。

Item 
    property bool ignoreNextChanged: false

    CustomCppItem  
        id: customItem

        onSomethingHappened: 
            ignoreNextChanged = true
            comboBox.currentIndex = 42
        
    

    ComboBox 
        id: comboBox

        currentIndex: -1
        onCurrentIndexChanged: 
            if(ignoreNextChanged) 
                ignoreNextChanged = false
                return
            

            // Removed code here
        
    

来自 Qt/C++,我想在这里使用某种QSignalBlocker,而不是我自己的财产。

Qml/QtQuick2 中是否有一些等价物?

【问题讨论】:

在不了解更多细节的情况下,试图阻止属性更改信号似乎有点像黑客攻击。你能详细说明你真正想要做什么吗?你可能有一个很好的理由,但可能有更好的方法...... 在我的例子中,CustomCppItem 是一个 QQuickPaintedItem,它调用了一个用于绘制地图的库。当我从组合框中选择一个项目时,我想告诉 MapItem 应该关注哪个区域。在某些情况下,我会覆盖我不想更改地图焦点的组合框选择。在这些情况下,我将 ignoreNextChanged 设置为 true。如果这已经是最好的方法,我不会改变它。 如何使用信号拦截器清除标志?目前它在您的信号处理程序中被清除。 我想我可以在currentIndex = 42 之后立即清除它,对吧? @DanielBrunner - 感谢您的解释。即使这都在同一个 QML 文件中,我说这很奇怪的原因是因为地图决定如何对组合框更改做出反应的逻辑是由 ComboBox 项而不是由 map/CusomCppItem 处理的本身。我会设置一个连接,以便CustomCppItem 可以监听comboBox.onCurrentIndexChanged 本身(或从onCurrentIndexChanged 抛出的另一个信号)。然后你的地图可以决定如何反应。 【参考方案1】:

为此,我将在 c++ 中实现 attached type:

signalblockerattachedtype.h

#ifndef SIGNALBLOCKERATTACHEDTYPE_H
#define SIGNALBLOCKERATTACHEDTYPE_H

#include <QObject>
#include <qqml.h>

class SignalBlockerAttachedType : public QObject

    Q_OBJECT
    Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)

public:
    explicit SignalBlockerAttachedType(QObject *object = nullptr) : QObject(object), m_object(object)
    
    

    ~SignalBlockerAttachedType() 
        if (m_object)
            m_object->blockSignals(false);
    

    bool enabled() const
    
        return m_enabled;
    
    void setEnabled(bool enabled)
    
        if (m_enabled == enabled)
            return;

        if (m_object)
            m_object->blockSignals(enabled);

        m_enabled = enabled;
        emit enabledChanged();
    

    static SignalBlockerAttachedType *qmlAttachedProperties(QObject *object) 
        return new SignalBlockerAttachedType(object);
    

signals:
    void enabledChanged();

private:
    bool m_enabled = false;
    QObject *m_object;
;

QML_DECLARE_TYPEINFO(SignalBlockerAttachedType, QML_HAS_ATTACHED_PROPERTIES)

#endif // SIGNALBLOCKERATTACHEDTYPE_H

ma​​in.cpp

#include "signalblockerattachedtype.h"
// ...
qmlRegisterUncreatableType<SignalBlockerAttachedType>("fr.grecko.SignalBlocker", 1, 0, "SignalBlocker", "SignalBlocker is only available as an attached type.");
// ...
engine.load(QUrl(QLatin1String("qrc:/usage.qml")));

usage.qml

import fr.grecko.SignalBlocker 1.0
// ...

Item 
    id: rootItem
    property alias currentIndex: comboBox.currentIndex
    onCurrentIndexChanged: 
        // this won't get called from a change in onSomethingHappened
    
    CustomCppItem  
        id: customItem

        onSomethingHappened: 
            rootItem.SignalBlocker.enabled = true;
            rootItem.currentIndex = 42
            rootItem.SignalBlocker.enabled = false;
        
    

    ComboBox 
        id: comboBox
        currentIndex: -1
    

即使SignalBlockerComboBox 上工作,您也不想将它放在ComboBox 上。这样做会阻止它在索引更改时更新其显示。

在你的情况下,我不认为这个解决方案比使用简单的标志更好。

【讨论】:

以上是关于Qml/QtQuick2 中的 QSignalBlocker?的主要内容,如果未能解决你的问题,请参考以下文章

Qml QtQuick2'无效的属性名称“样式”(M16)' [重复]

Qt Quick基础用法

在 Qt 5.0 中向 QML 公开 QAbstractListModel 元素属性

iOS Xcode 中的 UIViewController 中的 UIView 中的 UITableView

如何用ruby中的数组中的元素替换字符串中的单词?

如何将视图中的 javascript 代码中的对象列表传递给控制器​​中的操作方法