我试图包装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
在内部创建QQmlComponent
的MouseArea
的方法:
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,因为该实例还没有上下文或引擎。
唯一的问题是
MouseEvent
的pressed signal;它的参数是private API。您可能能够以某种方式封装该类,并为用户提供一个包含其所有属性的JavaScript对象,但是现在看来仅使用私有API会更容易。关于qt - QML与属性名称相同时无法发出信号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25953307/