如何创建QML自定义元素?


有时Qt中Declarativ模块提供元素不够用,这时我们可以根据自己需要创建自定义的元素。下面的例子
我们自己创建了一个Line的自定义元素。
qmlapp.pro
  1. QT  += core gui declarative

  2. TARGET = qmlapp
  3. TEMPLATE = app

  4. SOURCES += main.cpp
  5. HEADERS  += line.h
  6. OTHER_FILES += ui.qml
复制代码
新的元素需要继承自QDeclarativeItem,通过Q_PROPERTY我们可以为新的元素定义新的属性,
NOTIFY是用来通知绑定到这个属性的其他属性更新值。

line.h
  1. #ifndef LINE_H
  2. #define LINE_H

  3. #include <QDeclarativeItem>
  4. #include <QPainter>

  5. class Line : public QDeclarativeItem
  6. {
  7.     Q_OBJECT
  8.     Q_PROPERTY(int x1 READ x1 WRITE setX1 NOTIFY x1Changed);
  9.     Q_PROPERTY(int y1 READ y1 WRITE setY1 NOTIFY y1Changed);
  10.     Q_PROPERTY(int x2 READ x2 WRITE setX2 NOTIFY x2Changed);
  11.     Q_PROPERTY(int y2 READ y2 WRITE setY2 NOTIFY y2Changed);
  12.     Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged);
  13.     Q_PROPERTY(int penWidth READ penWidth WRITE setPenWidth NOTIFY penWidthChanged);

  14. public:
  15.     Line(QDeclarativeItem *parent = 0) :
  16.             QDeclarativeItem(parent), m_x1(0), m_y1(0), m_x2(0), m_y2(0),
  17.             m_color(Qt::black), m_penWidth(1)
  18.     {
  19.         // Important, otherwise the paint method is never called
  20.         setFlag(QGraphicsItem::ItemHasNoContents, false);
  21.     }

  22.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  23.     {
  24.         QPen pen(m_color, m_penWidth);
  25.         painter->setPen(pen);

  26.         if(smooth() == true) {
  27.             painter->setRenderHint(QPainter::Antialiasing, true);
  28.         }

  29.         int x = qMin(m_x1, m_x2) - m_penWidth/2;
  30.         int y = qMin(m_y1, m_y2) - m_penWidth/2;

  31.         painter->drawLine(m_x1 - x, m_y1 - y, m_x2 - x, m_y2 - y);
  32.     }

  33.     // Get methods
  34.     int x1() const { return m_x1; }
  35.     int y1() const { return m_y1; }
  36.     int x2() const { return m_x2; }
  37.     int y2() const { return m_y2; }
  38.     QColor color() const { return m_color; }
  39.     int penWidth() const { return m_penWidth; }

  40.     // Set methods
  41.     void setX1(int x1) {
  42.         if(m_x1 == x1) return;
  43.         m_x1 = x1;
  44.         updateSize();
  45.         emit x1Changed();
  46.         update();
  47.     }

  48.     void setY1(int y1) {
  49.         if(m_y1 == y1) return;
  50.         m_y1 = y1;
  51.         updateSize();
  52.         emit y1Changed();
  53.         update();
  54.     }

  55.     void setX2(int x2) {
  56.         if(m_x2 == x2) return;
  57.         m_x2 = x2;
  58.         updateSize();
  59.         emit x2Changed();
  60.         update();
  61.     }

  62.     void setY2(int y2) {
  63.         if(m_y2 == y2) return;
  64.         m_y2 = y2;
  65.         updateSize();
  66.         emit x2Changed();
  67.         update();
  68.     }

  69.     void setColor(const QColor &color) {
  70.         if(m_color == color) return;
  71.         m_color = color;
  72.         emit colorChanged();
  73.         update();
  74.     }

  75.     void setPenWidth(int newWidth) {
  76.         if(m_penWidth == newWidth) return;
  77.         m_penWidth = newWidth;
  78.         updateSize();
  79.         emit penWidthChanged();
  80.         update();
  81.     }

  82. signals:
  83.     void x1Changed();
  84.     void y1Changed();
  85.     void x2Changed();
  86.     void y2Changed();
  87.     void colorChanged();
  88.     void penWidthChanged();

  89. protected:
  90.     void updateSize() {
  91.         setX(qMin(m_x1, m_x2) - m_penWidth/2);
  92.         setY(qMin(m_y1, m_y2) - m_penWidth/2);
  93.         setWidth(qAbs(m_x2 - m_x1) + m_penWidth);
  94.         setHeight(qAbs(m_y2 - m_y1) + m_penWidth);
  95.     }

  96. protected:
  97.     int m_x1;
  98.     int m_y1;
  99.     int m_x2;
  100.     int m_y2;
  101.     QColor m_color;
  102.     int m_penWidth;
  103. };

  104. QML_DECLARE_TYPE(Line)

  105. #endif // LINE_H
复制代码
在main函数中,我们向QML系统中的版本号为1.0的自定义组件库CustomComponents中注册一个名为Line的QML元素。
main.cpp
  1. #include "line.h"
  2. #include <QApplication>
  3. #include <QDeclarativeView>

  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication a(argc, argv);

  7.     qmlRegisterType<Line>("CustomComponents", 1, 0, "Line");

  8.     QDeclarativeView view;
  9.     view.setSource(QUrl("./ui.qml"));
  10.     view.setResizeMode(QDeclarativeView::SizeRootObjectToView);

  11. #if defined(Q_WS_S60) || defined(Q_WS_MAEMO)
  12.     view.showMaximized();
  13. #else
  14.     view.setGeometry(100,100, 800, 480);
  15.     view.show();
  16. #endif
  17.     return a.exec();
  18. }
复制代码
在需要用到Line元素的QML文件中,我们需要导入1.0版本的CustomComponents库,这里面将包含我们的自定义元素Line
  1. ui.qml
  2. import CustomComponents 1.0
  3. import Qt 4.7

  4. Rectangle {
  5.     property bool evenClick : false

  6.     anchors.fill: parent; color: "lightsteelblue"

  7.     Line {
  8.         id: diagonalLine

  9.         anchors.fill: parent

  10.         Behavior on x1 { NumberAnimation { duration: 1000 } }
  11.         Behavior on y1 { NumberAnimation { duration: 1000 } }
  12.         Behavior on x2 { NumberAnimation { duration: 1000 } }
  13.         Behavior on y2 { NumberAnimation { duration: 1000 } }

  14.         x1: parent.x + 20; y1: parent.height / 2
  15.         x2: parent.width - 20; y2: parent.height / 2
  16.         color: "tomato"; penWidth: 3; smooth: true
  17.     }

  18.     MouseArea {
  19.         anchors.fill: parent
  20.         onClicked: {
  21.             if(evenClick) { diagonalLine.x1 = mouseX; diagonalLine.y1 = mouseY }
  22.             else { diagonalLine.x2 = mouseX; diagonalLine.y2 = mouseY }
  23.             evenClick = !evenClick
  24.         }
  25.     }

  26.     Text {
  27.         id: textX1Y1
  28.         anchors.left: parent.left; anchors.top: parent.top
  29.         text: "x1: " + diagonalLine.x1 + " y1: " + diagonalLine.y1
  30.     }

  31.     Text {
  32.         anchors.left: parent.left; anchors.top: textX1Y1.bottom; anchors.topMargin: 10
  33.         text: "x2: " + diagonalLine.x2 + " y2: " + diagonalLine.y2
  34.     }
  35. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值