已阅读:4,551 次
QML与C++混合编程
ian | C/C++,QT | 2011/03/04


QML是一种描述性的脚本语言,语法格式非常像javacript,QML可以在脚本里创建图形对象,并且支持各种图形特效,以及状态机等,同时又能跟Qt写的C++代码进行方便的交互,使用起来非常方便。这里介绍一下如何在QML里调用C++对象。

Qt Quick为我们提供了一些内建的QML Element,但是这些element类型太少,很多时候无法满足我们的需要,并且QML本质上只适合做界面的美化设计和交互功能,至于逻辑的处理,还是应当由C++来实现。

要在QML里使用我们自定义的对象,首先我们定义一个类,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "QDeclarativeItem"
#include "QColor"
class Chart : public QDeclarativeItem
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName)
    Q_PROPERTY(QColor color READ color WRITE setColor)
public:
    Chart (QDeclarativeItem *parent = 0);
 
    QString name() const { return m_name; }
    void setName(const QString &name) { m_name = name; }
    QColor color() const { return m_color; }
    void setColor(const QColor &color) { m_color = color; }
 
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
private:
    QString m_name;
    QColor m_color;
}

这里要注意,自定义的类一定要继承QObject。上面Q_PROPERTY宏的作用是声明这个类的属性,只有使用这个宏声明的属性,才可以在QML里面访问,这里可以看到声明了两个属性name和color,下面会有提到如何在QML里使用这个类。

下面是类的实现,这里只要简单重载一下paint方法就可以了:

1
2
3
4
5
6
7
8
9
10
11
12
Chart::Chart(QDeclarativeItem *parent)
    : QDeclarativeItem(parent)
{
    setFlag(QGraphicsItem::ItemHasNoContents, false);
}
void Chart::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    QPen pen(m_color, 2);
    painter->setPen(pen);
    painter->setRenderHints(QPainter::Antialiasing, true);
    painter->drawPie(boundingRect(), 90 * 16, 290 * 16);
}

下面我们就可以创建一个QML文件test.qml,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Charts 1.0
 
Item {
    width: 300; height: 200
 
    Chart {
        id: aChart
        anchors.centerIn: parent
        width: 100; height: 100
        name: "A simple pie chart"
        color: "red"
    }
 
    Text {
        anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
        text: aChart.name
    }
}

下面看看如何加载运行我们的QML文件,创建main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "chart.h"
#include "qdeclarative.h"
#include "QDeclarativeView"
#include "QApplication"
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    qmlRegisterType<Chart>("Charts", 1, 0, "Chart");
 
    QDeclarativeView view;
    view.setSource(QUrl::fromLocalFile("test.qml"));
    view.show();
    return app.exec();
}

这里调用了qmlRegisterType() 来注册 C++ 类 Chart 作为QML 中的Chart 类型,并将其放入版本号为1.0的”Charts”模块中。

然后就可以编译运行了,为了编译通过,需要在.pro 工程文件加入:

QT += declarative

下面再来看看如何在QML中调用C++的接口以及接收信号signal。

为c++类添加被调用的方法和信号

1
2
3
4
5
6
7
8
9
10
11
class Chart : public QDeclarativeItem
{
    ...
public:
    ...
    Q_INVOKABLE void clearChart();
 
signals:
    void chartCleared();
    ...
};

使用Q_INVOKABLE 使得Qt Meta-Object 系统可以访问到clearChart() 方法,于是QML也可以访问到这个方法了。

1
2
3
4
5
6
7
void PieChart::clearChart()
{
    setColor(QColor(Qt::transparent));
    update();
 
    emit chartCleared();
}

QML略做修改:

1
2
3
4
5
6
7
8
9
10
11
12
Item {
           …
        onChartCleared: console.log("The chart has been cleared")
    }
 
    MouseArea {
        ...
        onClicked: aChart.clearChart()
    }
          ...
    }
}

上面我们在MouseArea 的Clicked的事件中调用了Chart类的clearChart方法,当点击鼠标时,QML会调用clearChart清楚屏幕上的图形,然后发射chartCleared()信号,QML收到这个信号后又调用onChartCleared。这里onChartCleared这个槽函数和C++代码中的signal的命名似乎只是由一定的规则对应的,大家比较一下就知道了。

原创文章,转载请注明:转载自ian的个人博客[http://www.icodelogic.com]
本文链接地址: http://www.icodelogic.com/?p=55

tags:

没有评论

发表评论

你需要先 登录 才能回复