C++和QML混合编程

17 篇文章 1 订阅

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")
    }
}

这里写图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: QML(Qt Meta-Object Language)是一种用于构建用户界面的声明性语言,而C/C++是一种通用的编程语言。QML与C混合编程是使用这两种语言结合开发应用程序的一种方式。 在QML中,可以使用JavaScript进行逻辑编程和交互操作。而在C/C++中,可以进行复杂的计算、算法实现和底层操作。通过将这两种语言结合在一起,可以充分发挥它们各自的优势,提高应用程序的开发效率和性能。 使用QML与C混合编程时,通常会有一些场景需要注意。首先,需要在C/C++中编写一些类或者函数,然后在QML中进行调用。这就需要进行跨语言的接口和数据传递。通常可以使用Qt提供的机制,如信号与槽(signal and slot)来进行跨语言的通信。 其次,在QML中可以使用Qt的各种GUI组件来构建用户界面,而在C/C++中则可以处理一些底层的计算和数据操作。例如,可以在C/C++中使用Qt的数据结构和算法来处理复杂的数据逻辑,然后将结果传递给QML进行展示。 混合编程还可以提高应用程序的性能。QML中的JavaScript运行速度相对较慢,而C/C++则可以通过编译优化和底层操作来提高执行效率。因此,在一些对性能要求较高的场景下,可以将一些计算密集型的任务交给C/C++来处理,提高整体应用程序的性能。 总结来说,QML与C混合编程可以充分发挥两种语言各自的优势,提高应用程序的开发效率、性能和用户体验。通过合理地利用QML和C/C++,可以开发出功能强大、界面美观且性能优异的应用程序。 ### 回答2: QML(Qt Meta-Object Language)是一种用于快速构建用户界面的声明性编程语言,而C++是一种通用的编程语言。两者结合进行混合编程可以充分发挥各自的优势。 首先,QML具有直观易懂的语法,适合快速开发用户界面。它采用了类似于CSS的声明式风格,允许开发者通过组件和属性的方式构建用户交互界面。QML中可以直接调用C++函数和对象,并通过信号槽机制进行通信,这使得在QML中可以方便地使用C++的功能和库。 其次,C++是一种强大的编程语言,具有高效的性能和广泛的应用领域。通过与QML混合编程,我们可以利用C++的能力来处理复杂的业务逻辑和计算任务。例如,使用C++编写性能要求较高的算法,通过C++的多线程处理并发任务等。 混合编程可以通过QML中的Qt Quick Controls提供更丰富的用户界面控件和样式,通过C++编写的QML插件来实现一些复杂的界面逻辑或业务逻辑。这种结合可以在保持界面的灵活性和用户友好性的同时,实现高效的数据处理和计算。 总结来说,QMLC++混合编程方式可以在开发过程中充分利用两者的优势,快速构建用户界面并处理复杂的业务逻辑。这种结合使得开发人员能够更有效地开发出高性能、用户友好的应用程序。 ### 回答3: qml与C混合编程是指在Qt框架中,同时使用qml和C语言进行开发的一种方式。qml是Qt Quick的一种声明式语言,用于快速构建用户界面,而C语言是一种通用的编程语言,在Qt中常用于底层功能的实现。 qml与C混合编程的主要优点是可以充分利用qml的快速开发和灵活性和C语言的强大功能。qml具有直观的语法和简洁的代码风格,能够快速构建出美观且交互性强的用户界面。同时,qml也具有与C++进行无缝集成的能力,可以调用C++类和函数来实现一些高级的功能。而C语言作为一种通用的编程语言,具有底层的硬件控制和高性能的特点,适合用于一些需要高效计算和硬件交互的场景。通过qml与C混合编程,可以实现高效的用户界面和底层功能的结合,提供优秀的用户体验和性能。 在qml与C混合编程时,一般会使用Qt提供的接口和工具来实现qml与C语言的交互。Qt提供了QCoreApplication类和QObject类等接口,用于qml与C语言之间的通信和数据传递。可以通过qml提供的信号与槽机制,与C语言进行交互和传递数据。在qml中,可以调用C语言的函数来实现一些底层操作,比如文件读写、网络通信等。而在C语言中,可以通过Qt提供的接口,调用qml中的函数和属性,实现界面的更新和事件的处理。 总之,qml与C混合编程是一种灵活且强大的开发方式,可以充分发挥qml的优势和C语言的功能,实现高效的用户界面和底层功能的结合。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值