QML中使用QWidget子类导致程序崩溃,求解决方案
问题:继承QWidget的C++类在QML中使用导致崩溃
尝试在Qt C++中创建继承自QWidget的类,将其添加到QML时程序崩溃,崩溃前QDebug打印出"Constructed"。若改为继承QObject则程序运行正常,求修复建议。
相关代码
MyClass.h
#ifndef MYCLASS_H #define MYCLASS_H #include <QObject> #include <QWidget> class MyClass : public QWidget { private: Q_OBJECT public: MyClass(QWidget *parent = nullptr); ~MyClass(); }; #endif // MYCLASS_H
MyClass.cpp
#include "myclass.h" #include <QDebug> MyClass::MyClass(QWidget *parent): QWidget(parent) { qDebug() << "Constructed"; } MyClass::~MyClass() { qDebug() << "Deconstructed"; }
main.cpp
#include <QApplication> #include <QQmlApplicationEngine> #include "myclass.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); qmlRegisterType <MyClass> ("MyImport", 1, 0, "MyObject"); QQmlApplicationEngine engine; const QUrl url(u"qrc:/RectTest/main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml
import QtQuick import MyImport 1.0 Window { width: 640 height: 480 visible: true title: qsTr("Hello World") MyObject { id: obj } }
问题原因与修复方案
- 核心原因:QWidget属于Qt Widgets模块,遵循传统桌面控件的生命周期与渲染逻辑;而QML基于Qt Quick框架,元素继承自
QQuickItem,两者底层机制不兼容,无法直接将QWidget子类注册为QML类型实例化。
方案1:将QWidget嵌入QML
若只是需要在QML界面中显示现有QWidget控件,无需将其注册为QML类型,可通过QWidget::createWindowContainer将Widget包装为QML可识别的容器:
修改main.cpp相关代码:
int main(int argc, char *argv[]) { QApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/RectTest/main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [&](QObject *obj, const QUrl &objUrl) { if (obj && url == objUrl) { // 创建MyClass实例并包装为QML容器 MyClass *widget = new MyClass(); QQuickWidget *container = QWidget::createWindowContainer(widget, obj); container->setPosition(50, 50); container->setFixedSize(200, 200); } else if (!obj && url == objUrl) { QCoreApplication::exit(-1); } }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
同时删除QML中的MyObject声明。
方案2:实现QML原生自定义控件
若需要创建可直接在QML中使用的自定义控件,应继承Qt Quick的QQuickPaintedItem(适用于需要手动绘制的场景)或QQuickItem:
修改MyClass.h:
#ifndef MYCLASS_H #define MYCLASS_H #include <QQuickPaintedItem> #include <QPainter> class MyClass : public QQuickPaintedItem { Q_OBJECT public: explicit MyClass(QQuickItem *parent = nullptr); ~MyClass(); // 重写paint方法实现自定义绘制 void paint(QPainter *painter) override; }; #endif // MYCLASS_H
修改MyClass.cpp:
#include "myclass.h" #include <QDebug> MyClass::MyClass(QQuickItem *parent): QQuickPaintedItem(parent) { qDebug() << "Constructed"; } MyClass::~MyClass() { qDebug() << "Deconstructed"; } void MyClass::paint(QPainter *painter) { // 示例:绘制红色矩形 painter->setBrush(Qt::red); painter->drawRect(boundingRect()); }
main.cpp中的注册代码保持不变,QML中的MyObject声明也可以正常使用。
内容的提问来源于stack exchange,提问作者Edvin Wendt
相关产品推荐
相关产品推荐

