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
main.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
即使SignalBlocker
在ComboBox
上工作,您也不想将它放在ComboBox
上。这样做会阻止它在索引更改时更新其显示。
在你的情况下,我不认为这个解决方案比使用简单的标志更好。
【讨论】:
以上是关于Qml/QtQuick2 中的 QSignalBlocker?的主要内容,如果未能解决你的问题,请参考以下文章
Qml QtQuick2'无效的属性名称“样式”(M16)' [重复]
在 Qt 5.0 中向 QML 公开 QAbstractListModel 元素属性