问题:
我在 QWidget 中有一个 QQuickWidget,我正在将此小部件添加到 QMdiArea。我正尝试(plusBtn())
使用 从 C++调用 QML 函数QMetaObject::invokeMethod
。但是,当我尝试调用该方法时,我的应用程序崩溃了。只有当窗口添加到 QMdiArea 时才会发生此崩溃。当我从 QMdiArea 中删除小部件时,一切都正常。
这是我的简化代码:
QML(地图.qml):
import QtQuick
import QtLocation
import QtPositioning
Rectangle {
id: rectangle
Plugin {
id: mapPlugin
name: "osm"
}
Map {
id: mapView
anchors.fill: parent
plugin: mapPlugin
zoomLevel: 15
minimumZoomLevel: 2
activeMapType: supportedMapTypes[0]
}
function plusBtn() {
if (mapView.zoomLevel < mapView.maximumZoomLevel) {
mapView.zoomLevel = Math.round(mapView.zoomLevel + 1);
}
}
}
C++(主窗口实现):
#include <QDebug>
#include <QMainWindow>
#include <QPushButton>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickWidget>
#include <QVBoxLayout>
#include <QWidget>
#include <QApplication>
#include <QMDIArea>
class QmlWindow : public QWidget
{
public:
QmlWindow(QWidget* parent = nullptr)
: QWidget(parent)
{
QVBoxLayout* layout = new QVBoxLayout(this);
// Create and initialize the QQuickWidget
quickWidget = new QQuickWidget(this);
quickWidget->setSource(QUrl(QStringLiteral("qrc:/Map.qml")));
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
auto rootObj = quickWidget->rootObject();
// Create a button to invoke the QML method
QPushButton* button = new QPushButton("Call QML Method");
connect(button, &QPushButton::pressed, this, [=]() {
if (!rootObj) {
qWarning() << "Root object is null!";
return;
}
QMetaObject::invokeMethod(rootObj, "plusBtn");
});
layout->addWidget(quickWidget);
layout->addWidget(button);
setLayout(layout);
}
private:
QQuickWidget* quickWidget;
};
class MainWindow1 : public QMainWindow
{
public:
MainWindow1(QWidget* parent = nullptr)
: QMainWindow(parent)
{
mdiArea = new QMdiArea(this);
setCentralWidget(mdiArea);
QPushButton* openWindowBtn = new QPushButton("Open QML Window", this);
connect(openWindowBtn, &QPushButton::clicked, this, &MainWindow1::openQmlWindow);
setMenuWidget(openWindowBtn);
}
private:
void openQmlWindow()
{
QmlWindow* window = new QmlWindow();
QMdiSubWindow* subWindow = mdiArea->addSubWindow(window);
window->show();
}
QMdiArea* mdiArea;
};
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow1 mainWindow;
mainWindow.show();
return app.exec();
}
当我在窗口添加到 QMdiArea 后尝试调用 plusBtn() 时,会发生崩溃。有时应用程序会因分段错误而崩溃,有时我会收到消息:QMetaObject::invokeMethod:No such method QQuickPinchHandler::plusBtn()
我尝试的方法:我检查了 QQuickWidget 是否正确初始化,并且 setSource(QUrl("qrc:/Map.qml")) 加载 QML 文件没有问题。QML 文件加载正确,rootObject() 不为 nullptr,并且 QML 对象中存在方法 plusBtn()。只有当将小部件添加到 QMdiArea 时才会发生崩溃 — 如果在添加之前调用 plusBtn(),它会正常工作,但是一旦小部件位于 QMdiArea 内,调用 plusBtn() 有时会导致分段错误。
崩溃前的调试输出:
auto rootObj = ui->quickWidget->rootObject();
if (!rootObj) {
qWarning() << "Root object is null!";
return;
}
qDebug() << "Root object type:" << rootObj->metaObject()->className();
for (int i = 0; i < rootObj->metaObject()->methodCount(); ++i) {
qDebug() << "Method:" << rootObj->metaObject()->method(i).methodSignature();
}
输出:
Root object type: Map_QMLTYPE_0
Method: "plusBtn()"
我将非常感激任何关于为什么会发生这种情况以及如何解决它的见解。