目的
qml怎么嵌入widget的窗体内,并进行通信,这里用示例进行说明
1.创建工程
创建工程后,在pro中加入 QT += quickwidgets
2.创建资源文件
创建资源文件src.qrc,创建main.qml并加入资源文件中
3.创建窗体并关联
创建一个widget,并在里面加入一个layout用来放qml窗体。编辑widget.h文件,引入头文件#include <QQuickWidget>。创建qml窗体指针QQuickWidget *qmlWidget;, 增加两个被调用的函数
Q_INVOKABLE void doSomething();
public slots:
void printWidgetData();
完整代码
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QQuickWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//Q_INVOKABLE表示加入元对象系统,可以通过qml调用
Q_INVOKABLE void doSomething();
public slots:
void printWidgetData();
private:
Ui::Widget *ui;
QQuickWidget *qmlWidget;
};
#endif // WIDGET_H
在widget.cpp文件中,创建qml窗体qmlWidget = new QQuickWidget(this);,设置窗体的源qmlWidget->setSource(QUrl("qrc:/main.qml"));,然后设置一些qml属性,再把widget设置成qml的属性,并把qml放入widget的布局中,这样就关联起来了。代码是:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QQmlContext>
#include <QUrl>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
qmlWidget = new QQuickWidget(this);
qmlWidget->setSource(QUrl("qrc:/main.qml"));
//使root item适应窗口
qmlWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
qmlWidget->setClearColor(Qt::transparent);
qmlWidget->setAttribute(Qt::WA_AlwaysStackOnTop);
//将qml窗体放入layout中
ui->gridLayout_all->addWidget(qmlWidget);
//将widget对象设置成qml的属性
qmlWidget->rootContext()->setContextProperty("cppController", this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::doSomething()
{
qDebug()<<"widget method "<<__FUNCTION__<<" is called";
}
void Widget::printWidgetData()
{
qDebug() << "widget method " << __FUNCTION__ << " is called";
}
上面的步骤完成后,就已经可以运行了,完成了qml嵌入widget窗体的目标。
4.在qml中调用
为了使qml内容更直观,在里面增加了一个按钮。同时为了关连数据,按钮中调用了widget的函数。main.qml代码为
import QtQuick 2.15
import QtQuick.Controls 2.15
Rectangle {
anchors.fill: parent
color: "black"
visible: true
Button {
id: btn
width: 100
height: 100
x:400
y:1
text: "button"
onClicked: {
console.log("button pressed")
cppController.doSomething()
cppController.printWidgetData()
}
}
}
现在运行程序,界面是

点击按钮,终端会打印:
qml: button pressed
widget method doSomething is called
widget method printWidgetData is called
5. qml增加函数,widge访问qml中的函数
function printData() {
console.log("qml function is called")
}
在widget.cpp文件中获得qml的root item对象,然后访问printData()函数,还可以设置属性,具体代码为
main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
Rectangle {
anchors.fill: parent
color: "black"
visible: true
Button {
id: btn
width: 100
height: 100
x:400
y:1
text: "button"
onClicked: {
console.log("button pressed")
cppController.doSomething()
cppController.printWidgetData()
}
}
function printData() {
console.log("qml function is called")
}
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QQmlContext>
#include <QUrl>
#include <QQuickItem>
#include <QMetaObject>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
qmlWidget = new QQuickWidget(this);
qmlWidget->setSource(QUrl("qrc:/main.qml"));
//使root item适应窗口
qmlWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
qmlWidget->setClearColor(Qt::transparent);
qmlWidget->setAttribute(Qt::WA_AlwaysStackOnTop);
//将qml窗体放入layout中
ui->gridLayout_all->addWidget(qmlWidget);
//将widget对象设置成qml的属性
qmlWidget->rootContext()->setContextProperty("cppController", this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::doSomething()
{
qDebug()<<"widget method "<<__FUNCTION__<<" is called";
}
void Widget::printWidgetData()
{
qDebug() << "widget method " << __FUNCTION__
<< " is called, call qml function next";
QQuickItem *rootItem = qmlWidget->rootObject(); //获取qml的对象
QMetaObject::invokeMethod(rootItem, "printData"); //调用qml函数
rootItem->setProperty("color", QColor("green")); //还可以设置属性
}
运行程序,点击按钮,得到界面和输出是
这里我把窗体改成了绿色属性,然后通过qml的点击事件处理访问widget函数,用widget函数再访问qml函数:onClicked -> printWidgetData()->printData()。
结语
qml可以嵌入widget窗体,也可以互相调用函数。基本的数据通了以后,详细的可以根据实际情况修改,灵活多变,比如widget改成mainwindow也是可以的,由widget触发调用qml中的函数等。