【问题标题】:QSignalBlocker in Qml/QtQuick2?Qml/QtQuick2 中的 QSignalBlocker?
【发布时间】: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 抛出的另一个信号)。然后你的地图可以决定如何反应。

标签: qt qml qtquick2


【解决方案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 上。这样做会阻止它在索引更改时更新其显示。

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

【讨论】:

    猜你喜欢
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多