为什么要搞混合开发?
Qml已经越来越成为Qt开发的主流,相比与QWidget的界面开发更快,也更容易上手,实现效果上也更好。但老旧项目都是QWidget的框架,大家不可能一次性的把QWidget项目界面全部换成qml,这时候我们可以将新开发界面用qml。也可以用qml做一些控件供给QWidget用。
QWidget嵌入Qml的几种方式
- Qt4的QDeclarativeView
自己也没怎么接触过Qt4,这种方式不做评价,大概率也被Qt5的方式逐渐淘汰了
Qt4的QDeclarativeView *view = new QDeclarativeView;
view->setSource(QUrl(QStringLiteral("qrc:/test.qml"));
view->show();
- QWidget::createWindowContainer结合QQuickView
这种方式就是把加载Qml的window,通过createWindowContainer转换成一个QWidget,而QWidget作为外层widget的子控件;QQuickView创建出来的window作为加载qml的窗口,这个window作为createWindowContainer转换出来的小部件。
这种方式比较绕,并且使用过多的window会拖累程序的性能
QuickView *qml_view = new QQuickView();
qml_view->setResizeMode(QQuickView::SizeRootObjectToView);
qml_view->setSource(QUrl("test.qml"));
QWidget *widget_qml_view= QWidget::createWindowContainer(qml_view, nullptr);
ui.verticalLayout->addWidget(widget_qml_view);
qml_view->show();
- QQuickWidget
这种方式就很像我们在代码中动态创建QWidget小部件了。很方便也很容易懂。这也是官方推荐的一种方式。
QQuickWidget *qml_widget = new QQuickWidget(ui.widget_qml);
qml_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
qml_widget->setSource(QUrl("test.qml"));
qml_widget->show();
需要注意的点
- QuickView和QQuickWidget加载qml文件的小部件,根结点不能为Window,推荐为Item
- 避免使用QQuickWidget时调用winId(),可能会导致渲染问题
- 设置setResizeMode(SizeRootObjectToView)可以让qml控件跟随外层widget的大小进行变化
最后源码
import QtQuick 2.3
Rectangle {
color: "gray"
radius:10
Image {
id:background_image
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: "http://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
antialiasing: true
}
}
#include "QtUIDemo.h"
#include <QQuickWidget>
#include <QQmlApplicationEngine>
#include <QQuickView>
QtUIDemo::QtUIDemo(QWidget *parent) : QWidget(parent)
{
ui.setupUi(this);
//方式一
/*
QQuickView *qml_view = new QQuickView();
qml_view->setResizeMode(QQuickView::SizeRootObjectToView);
qml_view->setSource(QUrl("test_view.qml"));
QWidget *widget = QWidget::createWindowContainer(qml_view, nullptr);
ui.verticalLayout->addWidget(widget);
qml_view->show();
*/
//方式二 推荐
QQuickWidget *qml_widget = new QQuickWidget();
qml_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
qml_widget->setSource(QUrl("test_view.qml"));
qml_widget->show();
ui.verticalLayout->addWidget(qml_widget);
}