QML如果与属性同名,则无法发出信号

时间:2014-09-20 21:08:53

标签: qt qml

我试图打包MouseArea来定制它的行为并遇到一个奇怪的问题。下面的示例代码演示了这个问题:

import QtQuick 2.3

Item {
    id: base
    width: 100
    height: 100
    anchors.fill: parent

    property alias pressed: area.pressed

    signal pressed( var mouse )

    MouseArea {
        id: area
        anchors.fill: parent

        onPressed: {
            base.pressed( mouse );
        }
    }
}

单击矩形会导致此错误:

  

TypeError:Property' press'对象QmlTest_QMLTYPE_0(0x1b4c780)不是函数

显然,它试图调用属性pressed而不是信号pressed。这有解决方法吗?请记住,界面必须模仿MouseArea,因此需要同时具有pressed属性信号。

这确实让我觉得它是一个错误,显然MouseArea管理它,但它是从C ++声明的。我知道任何稍微复杂的QML问题的通常答案是"在C ++"中做,但因为绝大多数QtQuick类是私有的,所以它通常不实用。

1 个答案:

答案 0 :(得分:1)

听起来你自己已经回答了这个问题。我怀疑QML中是否有针对此问题的解决方法,答案可能是#34;在C ++中做到这一点" - 但我无法肯定地说。

以下是如何在C ++中执行此操作,定义使用QQuickItem在内部创建MouseArea的{​​{1}}:

的main.cpp

QQmlComponent

main.qml

#include <QGuiApplication>
#include <QtQml>
#include <QtQuick>

class CustomMouseArea : public QQuickItem
{
    Q_OBJECT

    Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
public:
    CustomMouseArea() :
        mMouseArea(0)
    {
    }

    // Can't use constructor, as we don't have a QQmlContext by that stage.
    void componentComplete() {
        QQmlComponent component(qmlEngine(this), QUrl(QStringLiteral("qrc:///InternalMouseArea.qml")));
        if (component.status() != QQmlComponent::Ready) {
            qDebug() << component.errorString();
            return;
        }

        mMouseArea = qobject_cast<QQuickItem*>(component.create());
        Q_ASSERT(mMouseArea);
        mMouseArea->setParentItem(this);

        connect(mMouseArea, SIGNAL(pressedChanged()), this, SIGNAL(pressedChanged()));

        // Don't forget to call the base class' implementation, or no child items will show up! :)
        QQuickItem::componentComplete();
    }

    bool pressed() const {
        return mMouseArea->property("pressed").toBool();
    }
signals:
    void pressedChanged();
private:
    QQuickItem *mMouseArea;
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<CustomMouseArea>("Test", 1, 0, "CustomMouseArea");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec();
}

#include "main.moc"

InternalMouseArea.qml

import QtQuick 2.3
import QtQuick.Controls 1.2

import Test 1.0

ApplicationWindow {
    width: 400
    height: 400
    color: "green"
    visible: true

    CustomMouseArea {
        anchors.fill: parent

        onPressedChanged: print("pressed =", pressed)
    }
}

首先我使用构造函数创建import QtQuick 2.0 MouseArea { anchors.fill: parent } 并想知道为什么我有一个空MouseArea,然后发现它是documented not to have a context at that stage

  

请注意,当在QObject子类的构造函数内部调用时,这些函数将返回null,因为该实例还没有上下文或引擎。

唯一的问题是QQmlEngine的{​​{3}};其MouseArea参数为pressed signal。您可能能够以某种方式封装该类,并为用户提供包含其所有属性的JavaScript对象,但此时似乎更容易使用私有API。