我试图包装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:对象QmlTest_QMLTYPE_0(0x1b4c780)的属性'pressed'不是函数


显然,它试图调用属性pressed而不是信号pressed。有没有解决方法?请记住,接口必须模仿MouseArea,因此必须同时具有pressed属性和信号。

确实,这确实使我成为一个bug,很明显MouseArea可以管理它,但是它是从C ++声明的。我知道,对于任何稍微复杂的QML问题,通常的答案是“在C ++中执行”,但是由于绝大多数QtQuick类都是私有的,因此通常不切实际。

最佳答案

听起来您已经自己回答了这个问题。我怀疑在QML中是否有解决方法,答案可能是“在C ++中完成”-我不能肯定地说。

这是在C ++中定义QQuickItem并使用MouseArea在内部创建QQmlComponentMouseArea的方法:

main.cpp

#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"


main.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)
    }
}


InternalMouseArea.qml

import QtQuick 2.0

MouseArea {
    anchors.fill: parent
}


最初,我使用构造函数创建了QQmlEngine,想知道为什么我有一个空的MouseArea,然后发现它是documented not to have a context at that stage


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


唯一的问题是MouseEventpressed signal;它的参数是private API。您可能能够以某种方式封装该类,并为用户提供一个包含其所有属性的JavaScript对象,但是现在看来仅使用私有API会更容易。

关于qt - QML与属性名称相同时无法发出信号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25953307/

10-15 23:19