c++访问QML中的控件
- main.qml如下所示:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
// 定义一个带参信号
signal sigTest(value: string, count: int)
// sigTest信号的信号处理器
onSigTest: {
console.log(value, count)
}
function func() {
return "func"
}
}
- main.cpp代码如下所示:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreated,
&app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
// 根据QQmlApplicationEngine获取对象树根节点
QObject* obj = engine.rootObjects().first();
// 修改QML中控件的属性--更改标题
QQmlProperty(obj, "title").write("test");
// 调用QML中控件的信号
QMetaObject::invokeMethod(obj, "sigTest", Q_ARG(QString, "call onSigTest"), Q_ARG(int, 1024));
// 调用QML中控件的方法
QVariant ret;
QMetaObject::invokeMethod(obj, "func", Q_RETURN_ARG(QVariant, ret));
// 获取方法返回值
qDebug() << ret;
return app.exec();
}
QML访问c++中类的属性和方法
方式1:将c++类型注册为QML系统可以使用的类型
这种方式下,使用注册成功的C++类型与使用其他控件类型一样,进行声明式创建实例
- 示例类如下:
#ifndef TEST_H
#define TEST_H
#include <QObject>
class Test : public QObject
{
Q_OBJECT
public:
explicit Test(QObject *parent = nullptr);
Q_INVOKABLE int age() const;
Q_INVOKABLE void setAge(int newAge);
signals:
void ageChanged();
private:
int m_age = 24;
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged FINAL)
};
#endif // TEST_H
#include "test.h"
Test::Test(QObject *parent)
: QObject{parent}
{}
int Test::age() const
{
return m_age;
}
void Test::setAge(int newAge)
{
if (m_age == newAge)
return;
m_age = newAge;
emit ageChanged();
}
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include "test.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreated,
&app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
// 在QML类型中注册c++类型
qmlRegisterType<Test>("Test",1, 0, "Test");
engine.load(url);
return app.exec();
}
- qml示例如下:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import Test 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
width: 100
height: 20
Text {
id: name
text: test.age // 使用cpp类中的属性
anchors.centerIn: parent
Component.onCompleted: {
test.age = 1024
test.setAge(1026)
}
}
anchors.centerIn: parent
color: "yellow"
}
Test {
id: test
}
}
方式2:将c++实例注册到 QML 系统中
示例如下:
- myviewmodel.h
#ifndef MYVIEWMODEL_H
#define MYVIEWMODEL_H
#include <QObject>
#include <QString>
class MyViewModel : public QObject
{
Q_OBJECT
//--------提供给QML访问的属性--------
// FINAL关键字表示禁止子类重写该属性
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged FINAL)
public:
MyViewModel(QObject* parent = nullptr);
~MyViewModel();
QString source();
void setSource(QString source);
//---------提供给QML调用的函数接口--------
Q_INVOKABLE void on_btn_clicked();
signals:
void sourceChanged(const QString& source);
private:
QString m_source;
};
#endif // MYVIEWMODEL_H
- myviewmodel.cpp
#include "myviewmodel.h"
#include <QDebug>
MyViewModel::MyViewModel(QObject* parent) : QObject(parent) {}
MyViewModel::~MyViewModel() {
}
QString MyViewModel::source() {
return m_source;
}
void MyViewModel::setSource(QString source) {
qDebug() << "修改前,source值为:" << this->m_source;
if (this->m_source != source) {
this->m_source = source;
// 重要,触发页面更新
emit sourceChanged(this->m_source);
}
}
void MyViewModel::on_btn_clicked() {
qDebug() << "组件内部按钮点击事件的执行动作";
}
- main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
#include "myviewmodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
// QQuickStyle::setStyle("Material");
QQmlApplicationEngine engine;
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreationFailed,
&app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
// 将 C++ 实例注册到 QML 系统中
MyViewModel* viewModel = new MyViewModel(&app);
qmlRegisterSingletonInstance("nrvcer.test", 1, 0, "MyViewModel", viewModel);
engine.loadFromModule("test_wrap_components", "Main");
return app.exec();
}
- CustomComponents.qml
import QtQuick
Item {
id: root
property string source // 属性接收图片源
signal pass()
Image {
id: image
width: 300
height: 300
source: root.source
fillMode: Image.PreserveAspectFit
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
Item {
id: item
width: 200
height: 100
anchors.top: image.bottom
anchors.topMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
id: rec1
anchors.fill: parent
radius: 20
Text {
text: "向组件使用者发出信号,让上层决定按钮行为"
anchors.centerIn: parent
wrapMode: Text.WrapAnywhere
}
MouseArea {
anchors.fill: parent
enabled: true
// 触发信号,等同于emit pass()
onClicked:root.pass()
}
}
}
Item {
width: 200
height: 100
anchors.top: item.bottom
anchors.topMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
anchors.topMargin: 20
anchors.fill: parent
radius: 20
Text {
text: "测试修改source"
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
enabled: true
onClicked: {
// 这里会调用MyViewModel的setSource方法
viewModel.source = "images/back.png"
}
}
}
}
}
- Main.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import test_wrap_components
import nrvcer.test 1.0
ApplicationWindow {
width: 1920
height: 1080
visible: true
property var viewModel: MyViewModel
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
CustomComponents {
id: customComponents
source: viewModel.source
onPass: viewModel.on_btn_clicked()
}
}
}
浙公网安备 33010602011771号