QML中使用C++对象
官方文档:http://doc.qt.io/qt-5/qtqml-tutorials-extending-qml-example.html
创建一个新类型
创建C++对象
piechart.h
#ifndef PIECHART_H
#define PIECHART_H
#include <QtQuick/QQuickPaintedItem>
#include <QColor>
#include <QPainter>
class PieChart : public QQuickPaintedItem
{
//为了使用信号和槽系统和QML交互
Q_OBJECT
//Q_PROPERTY是QObject的宏定义,具体的含义可以去QObject中去查看
//这里的意思是PieChart有一个属性name,获取属性的函数名是name,设置属性的函数名是setName
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QColor color READ color WRITE setColor)
public:
PieChart(QQuickItem *parent=0);
QString name() const;
void setName(const QString &name);
QColor color() const;
void setColor(const QColor &color);
void paint(QPainter *painter);
private:
QString myName;
QColor myColor;
};
#endif // PIECHART_H
piechart.cpp
#include "piechart.h"
#include <QPainter>
PieChart::PieChart(QQuickItem *parent)
:QQuickPaintedItem(parent)
{
}
QString PieChart::name() const
{
return myName;
}
void PieChart::setName(const QString &name)
{
myName = name;
}
QColor PieChart::color() const
{
return myColor;
}
void PieChart::setColor(const QColor &color)
{
myColor = color;
}
void PieChart::paint(QPainter *painter)
{
QPen pen(myColor, 2);
painter->setPen(pen);
painter->setRenderHints(QPainter::Antialiasing, true);
painter->drawPie(boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16);
}
将C++对象注册到QML中
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <piechart.h>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
//4个参数的含义是,包名,主版本号,此版本好,QML类型名
qmlRegisterType<PieChart>("Charts",1,0,"PieChart");
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
在QML中使用C++注册到QML中的对象
main.qml
import QtQuick 2.7
import QtQuick.Controls 1.4
import Charts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
PieChart {
id: aPieChart
anchors.centerIn: parent
width: 100; height: 100
name: "A simple pie chart"
//这里自动转换为C++中的QColor类型
color: "red"
}
Text {
anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: aPieChart.name
}
}
QML和C++数据类型转换
http://doc.qt.io/qt-5/qtqml-cppintegration-data.html
连接C++的方法和信号
点击控件,图形消失,并且在QML中处理chartCleared信号
piechart.h增加的代码
public:
//将这个方法注册到元对象系统中,这样QML就能直接调用这个方法
Q_INVOKABLE void clearChart();
signals:
void chartCleared();
piechart.cpp增加的代码
void PieChart::clearChart()
{
setColor(QColor(Qt::transparent));
update();
emit chartCleared();
}
main.qml的代码变为如下
import QtQuick 2.7
import QtQuick.Controls 1.4
import Charts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
PieChart {
id: aPieChart
anchors.centerIn: parent
width: 100; height: 100
color: "red"
onChartCleared: console.log("The chart has been cleared")
}
MouseArea {
anchors.fill: parent
onClicked: aPieChart.clearChart()
}
Text {
anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: "Click anywhere to clear the chart"
}
}
属性绑定
2个图形A和B,B的颜色就是A的颜色,点击整个控件,A的颜色变化,如果属性不绑定,就只有A的颜色发生变化,因为B不知道A的颜色发生变化,属性绑定后A和B的颜色会一起变化
piechart.h增加和修改的代码
//当color这个属性发生变化时,发送colorChanged这个信号,更新这个属性
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
signals:
void colorChanged();
piechart.cpp修改的代码如下
void PieChart::setColor(const QColor &color)
{
if (color != myColor)
{
myColor = color;
update(); // repaint with the new color
emit colorChanged();
}
}
main.qml
import QtQuick 2.7
import QtQuick.Controls 1.4
import Charts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Row {
anchors.centerIn: parent
spacing: 20
PieChart {
id: chartA
width: 100; height: 100
color: "red"
}
PieChart {
id: chartB
width: 100; height: 100
color: chartA.color
}
}
MouseArea {
anchors.fill: parent
onClicked: { chartA.color = "blue" }
}
Text {
anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: "Click anywhere to change the chart color"
}
}
使用自定义属性类型
C++中使用QML对象
官方文档:http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html
从C++中加载QML对象
按照官方文档写一直不对,也不知道问题出在哪里,就按照Qt Quick核心编程上的例子写了
通过C++改变QML文档中Item的宽度
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
objectName: "window"
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item {
objectName: "item"
width: 100
height: 100
Rectangle {
anchors.fill: parent
border.width: 1
}
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QList>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QList<QObject*> rootObjects = engine.rootObjects();
int count = rootObjects.size();
QObject *root = NULL;
for(int i=0; i<count; i++)
{
if(rootObjects.at(i)->objectName() == "window")
{
root = rootObjects.at(i);
break;
}
}
QObject *item = root->findChild<QObject*>("item");
//判断是否是空指针
if(item)
{
item->setProperty("width","200");
}
return app.exec();
}
QML中定义的是正方形,显示出来是长方形
从C++获取QML对象的成员
属性
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
objectName: "window"
visible: true
width: 640
height: 480
property int someNumber: 100
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QList>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QList<QObject*> rootObjects = engine.rootObjects();
int count = rootObjects.size();
QObject *root = NULL;
for(int i=0; i<count; i++)
{
if(rootObjects.at(i)->objectName() == "window")
{
root = rootObjects.at(i);
break;
}
}
qDebug() << "Property value:" << QQmlProperty::read(root, "someNumber").toInt();
QQmlProperty::write(root, "someNumber", 5000);
qDebug() << "Property value:" << root->property("someNumber").toInt();
root->setProperty("someNumber", 100);
return app.exec();
}
调用QML方法
在C++中调用QML中的方法
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
objectName: "window"
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function myQmlFunction(msg) {
console.log("Got Message",msg)
return "some return value"
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QDebug>
#include <QMetaObject>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QList<QObject*> rootObjects = engine.rootObjects();
int count = rootObjects.size();
QObject *root = NULL;
for(int i=0; i<count; i++)
{
if(rootObjects.at(i)->objectName() == "window")
{
root = rootObjects.at(i);
break;
}
}
QVariant returnedValue;
QVariant msg = "Hello from C++";
//参数含义:被调用对象的指针,方法名字,返回值,参数
QMetaObject::invokeMethod(root, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
qDebug() << "QML function returned:" << returnedValue.toString();
//这个是运行完毕删除图形界面
delete root;
return app.exec();
}
连接QML的信号
在C++中接收QML中发出的信号
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public slots:
void cppSlot(const QString &msg) {
qDebug() << "Called the C++ slot with message:" << msg;
}
};
#endif // MYCLASS_H
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QDebug>
#include <QMetaObject>
#include <myclass.h>
#include <QQuickView>
#include <QQuickItem>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
QList<QObject*> rootObjects = engine.rootObjects();
int count = rootObjects.size();
QObject *root = NULL;
for(int i=0; i<count; i++)
{
if(rootObjects.at(i)->objectName() == "window")
{
root = rootObjects.at(i);
break;
}
}
MyClass myClass;
QObject::connect(root, SIGNAL(qmlSignal(QString)),
&myClass, SLOT(cppSlot(QString)));
return app.exec();
}
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
objectName: "window"
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
signal qmlSignal(string msg)
MouseArea {
anchors.fill: parent
onClicked: window.qmlSignal("Hello from QML")
}
}