本文共 3235 字,大约阅读时间需要 10 分钟。
在使用 Qt Widgets 时,经常要实现一些比较炫酷的效果(例如:滑动、翻页),这时选择 QML 会显得非常简单。
那么,问题来了:
版权所有:一去丶二三里,转载请注明出处:
创建了一个简单的 QML 文件,用于显示一个绿色的矩形,其中包含一个文本。为了说明 QML 与 Qt Widgets 的交互,在矩形中添加了两个信号。
import QtQuick 2.1Rectangle { id: root color: "green" width: 200 height: 200 // 发送给 Qt Widgets 的信号 signal qmlSignal // 从 Qt Widgets 接收到的信号 signal cSignal Text { id: myText text: "Click me" font.pointSize: 14 anchors.centerIn: parent } MouseArea { anchors.fill: parent onClicked: qmlSignal() } // 信号处理程序(处理从 Qt Widgets 接收到的信号) onCSignal: { root.color = "blue" myText.text = "Call the qml signal handler" }}
如果需要,可以将像往常一样使用 qmlscene 来运行。
要加载和显示 QML,可以使用以下两种方式:
QQuickWidget
QQuickView
无论使用哪种方式,一旦主源文件的 URL 被指定,都将自动加载和显示 QML 视图。
注意: 在 中,还介绍了另一种方式 - QQmlEngine + QQmlComponent
,但是这种方式不能以 view 的形式加载。
QQuickWidget 是 Qt 5.3 中提供的一个类,继承自 QWidget,它是 QQuickWindow 一个很方便的包装器,用于显示 Qt Quick 用户界面。
使用方式:
QQuickWidget *view = new QQuickWidget;view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));view->show();
QQuickView 是 Qt 5.0 中提供的一个类,继承自 QQuickWindow(继承自 QWindow),用于显示 Qt Quick 用户界面。
使用方式:
QQuickView *view = new QQuickView;view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));view->show();
可以看到,两者的使用方式几乎没什么区别。但是,QQuickWidget 基于 QWidget,而 QQuickView 基于 QWindow,所以需要将其转换为 QWidget,才能与 Qt Widgets 相结合。
这样,就需要再引入一个函数:
[static] QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags())
该函数用于创建一个 QWidget,可以将 window 嵌入到基于 QWidget 的应用程序中。
所以,要将 QQuickView 转为 QWidget,可以使用下述方式:
QQuickView *view = new QQuickView();QWidget *widget = QWidget::createWindowContainer(view, this);view->setSource(QUrl("qrc:/main.qml"));
当一切准备就绪,就可以将 QML 与 Qt Widgets 完美结合在一起了:
最终效果:
源码如下:
#include "widget.h"#include#include #include Widget::Widget(QWidget *parent) : QWidget(parent){ resize(300, 300); // 方式一 // QQuickView *pView = new QQuickView(); // QWidget *pWidget = QWidget::createWindowContainer(pView, this); // pView->setResizeMode(QQuickView::SizeRootObjectToView); // pView->setSource(QUrl("qrc:/main.qml")); // 方式二 QQuickWidget *pWidget = new QQuickWidget(); pWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); pWidget->setSource(QUrl("qrc:/main.qml")); m_pButton = new QPushButton(this); m_pButton->setText("Qt Widgets..."); QVBoxLayout *pLayout = new QVBoxLayout(); pLayout->addWidget(pWidget); pLayout->addWidget(m_pButton); pLayout->setSpacing(10); pLayout->setContentsMargins(10, 10, 10, 10); setLayout(pLayout); // QML 与 Qt Widgets 通信 // QObject *pRoot = (QObject*)pView->rootObject(); QObject *pRoot = (QObject*)pWidget->rootObject(); if (pRoot != NULL) { connect(pRoot, SIGNAL(qmlSignal()), this, SLOT(receiveFromQml())); connect(m_pButton, SIGNAL(clicked(bool)), pRoot, SIGNAL(cSignal())); }}void Widget::receiveFromQml(){ m_pButton->setText("Call the C++ slot");}
结合之后,少不了通信,这里采用信号槽的方式,通过 QML 的根元素 root 来发送和接收信号。