zoukankan      html  css  js  c++  java
  • QML基础

    BASIC

    QWidget 和 QML

    QWidgets were designed for a different type of user interface than QML, so it is not always a good idea to port a QWidget-based application to QML.

    QWidgets are a better choice if your UI is comprised of a small number of complex and static elements.

    QML is a better choice if your UI is comprised of a large number of simple and dynamic elements.

    QtQuick提供了一套动态的QML元素来定制UI的Framework, 帮助程序员和设计师合作为便携式设备建立流畅的UI; 

    QML是对JavaScript的一种扩展, 使用QML元素来构建对象树, 对QObject base类型系统进行改善, 支持自动属性绑定;

    Dependency

    QtDeclarative: QtCore, QtGui, QtNetwork, QtOpenGL, QtScript, QtSql, QtSvg, QtXmlPatterns

    http://qt-project.org/wiki/Qt_Library_Cross_Dependencies

    QML语言格式

    对象是指定的类型, 首字母大写, 使用大括号;

    Image {       
        source: "pics/logo.png"
        anchors.centerIn: parent       
    }
    

    属性指定, property: value

    属性一般以单行指定, 也可以指定多个属性, 使用分号作为语句的结束;

    Rectangle {  100; height: 100 }
    

    Import语句: import Qt 4.8 OR import QtQuick 1.1, 表示将QML元素或QtQuick库包含进来;

    JS表达式

    属性可以和表达式绑定, 还可以通过id引用其他对象的属性;

    Text {       
        id: text1       
        text: "Hello World"
    }       
    Text {       
        id: text2       
        text: text1.text       
    }
    

    QML注释 单行 //...     多行 /*...*/

    属性

    通常首字母小写; property int textId;

    属性类型: 整型int, 实数real, 布尔bool, 字符串string, 颜色color, 列表等;

    QML属性会进行类型安全检测;

    x: "hello" // illegal!
    

    id 每个对象有一个唯一的属性-id, 同一个QML文件不能出现同名的id; id可以被对象以及脚本使用;

    Note id首字符必须是小写字符或下划线, 不能包含除字母,数字和下划线以外的字符;

    列表属性

    Item {       
        children: [       
            Image {},       
            Text {}       
        ]       
    }
    

    对于单一项目列表, 可以省略方括号

    Image {       
        children: Rectangle {}       
    }
    

    默认属性: 属性标记可省略

    State {       
    changes: [//可省略       
        PropertyChanges {},       
        PropertyChanges {}       
    ]//可省略       
    }
    

    分组属性: 使用点操作符 '.' 或分组符号

    Text {       
        font.pixelSize: 12       
        font.bold: true
    }       
    Text {       
        font { pixelSize: 12; bold: true }       
    }
    

    对象属性: Type.property;

    信号处理

    MouseArea {       
        acceptedButtons: Qt.LeftButton | Qt.RightButton       
        onPressed: if (mouse.button == Qt.RightButton)     console.log("Right mouse button pressed")       
    }
    

    设置别名

    property alias someName: element.property

    QML定义signal

    signal signalName(type Property)

    使用时定义slot: 'onSignalName'

     

    QtQuick针对C++开发者入门

    Qt Framework运行性能高, 占内存小, 适合开发移动, 嵌入式与上网本的App;

    QML是描述性语言, 适合设计师编写; QML整合了JavaScript与Qt现存的QObject类型系统;

    QtQuick包含QML, QDeclarative模块, 以及QtCreator等工具;

    QML文档可以是本地文件, 网络资源或者直接构建的文本数据; QML也是一个版本化的语言: import Lib version;

    默认属性 children: [Text {},Rectangle {}]; resources: [Timer {}]

    锚属性: anchors, 目前有17个;

    可视化透明度 opacity: real; 在动画中应该谨慎使用, 多个图层进行渲染将导致性能下降; 最好在最终部署前对尽可能多的场景做预渲染;

    子对象对于某些属性可以继承自父级对象;

    互动元素

    MouseArea - Flickable, Flipable, FocusScope; 可以使用JavaScript表达式;

    状态声明 state

    动画 Transitions, Animation 

    QML视图模式 ListView GridView ListModel ListElement PathView C++QAbstractItemModel

    QML文档是UTF-8编码格式的;

    ---End---

     

    QML与Qt程序

    Qt Declarative UI运行环境

    QML文档通过QML运行环境载入并运行. 包含Declarative UI引擎和内置的QML元素, 插件模块, 还提供了访问第三方的QML元素与模块.

    QML与Qt

    单纯使用QML可以不了解Qt, 但是如果想设计一个数据逻辑和UI分开的结构, 则需要用到Qt;

    QML可直接访问的Qt类:

    QAction, signal and slot(can be used as function in JavaScript),

    QWidget--QDeclarativeView(Qt5使用QQuickView代替, 属于QWindow, 不用QWidget),

    Qt Model--QAbstractItemModel

    QML Tools

    查看和调试QML的工具: qmlviewer

    command: qmlviewer.exe filename.qml

    将C++类注册成为QML类型

    #include <QtQml>       
    qmlRegisterType<MySliderItem>("com.mycompany.qmlcomponents", 1, 0, "Slider");
    

    使用:

    import com.mycompany.qmlcomponents 1.0       
    Slider {       
        // ...       
    }

    以C++类创建QML属性

    1)inherited from QObject

    2)declarate the Marco: Q_OBJECT(meta system), Q_PROPERTY(QML property)

    Declarative UI

    QDeclarativeView加载QML文件

    QDeclarativeView是一个QWidget(QAbstractScrollArea), 可以加载QML文件;

    QDeclarativeView view;       
    view.setSource(QUrl::fromLocalFile("app.qml"));       
    view.show();
    

    PRO工程文件

    QT += gui declarative
    

    QDeclarativeEngine

    可以直接加载QML, 创建QObject来进行操作;
    每个程序至少需要一个Engine, 可以配置全局设置应用到所有的QML组件中;

    QDeclarativeEngine: 提供了一个实例化QML Component的环境;
    QDeclarativeComponent: 封装QML Component的一个类;
    QDeclarativeContext: 定义了一个通过QML engine工作的context, 可以将数据暴露给QML component;

    QDeclarativeEngine engine;
    QDeclarativeContext *windowContext = new QDeclarativeContext(engine.rootContext());
    QDeclarativeComponent component(&engine, "application.qml");
    QObject *window = component.create(windowContext);
    

    Note 对于shadow build, qml文件需要放到build路径中;

    加上数据

    >背景颜色

    QDeclarativeContext *context = view.rootContext();
    context->setContextProperty("backgroundColor",QColor(Qt::yellow));
    view.setSource(QUrl::fromLocalFile("main.qml"));
    

    当不需要QDeclarativeView显示组件时, 可以使用QDeclarativeEngine::rootContext()代替

    QDeclarativeContext *windowContext = new QDeclarativeContext(engine.rootContext());
    

    QDeclarativeContexts是树形结构, 除了root context每个QDeclarativeContexts都有一个父级, 子级QDeclarativeContexts继承父级的context属性.
    这样应用程序分隔不同数据导出到不同的QML对象实例有更多自由性.

    结构化数据

    除了QVariant支持内置数据类型外, QObject的派生类型也可以分配给context;

    class CustomPalette : public QObject{
        Q_OBJECT
        Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY backgroundChanged)
        Q_PROPERTY(QColor text READ text WRITE setText NOTIFY textChanged)
    ...}
    //...
    view.rootContext()->setContextProperty("palette", new CustomPalette);
    

    在QML中;

    Rectangle {
    color: palette.background }
    

    在属性改变时, Notify信号会被发出;(需要实现Notify, 在发出信号时注意判断值是否改变)

    QML调用C++

    public slots或者Q_INVOKEABLE模式下的函数可以被QObject调用;

    QML支持的返回值类型: bool; unsigned int, int; float, double, qreal; QString; QUrl; QColor; QDate,QTime,QDateTime; QPoint,QPointF; QSize,QSizeF; QRect,QRectF; QVariant;

    Q_INVOKABLE bool isRunning() const;
    public slots:
        void start();
        void stop();
    

    作为context导入QML;

    view.rootContext()->setContextProperty("stopwatch",new Stopwatch);
    

    QML中使用;

    onClicked: {
    if (stopwatch.isRunning())
        stopwatch.stop()
    else
        stopwatch.start();
    }
    

    更有效率的写法:

    onClicked: stopwatch.running = !stopwatch.running
    

    网络组件

    如果QML或图片等是网络资源, QDeclarativeComponent要先获取网络数据, 才可以创建对象.

    QDeclarativeComponent::statusChanged()和continueLoading(), 还需要防止组件是缓存中保存的;

    MyApplication::MyApplication()
    {
    // ...
        component = new QDeclarativeComponent(engine, QUrl("http://www.example.com/main.qml"));
    if (component->isLoading())
        QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueLoading()));
    else
        continueLoading();
    }
    void MyApplication::continueLoading()
    {
    if (component->isError()) {
        qWarning() << component->errors();
    } 
    else {
        QObject *myObject = component->create();
    }
    }
    

    Qt资源

    qrc是XML格式的文件, 会被rcc工具编译成object文件, 链接到动态库(shared library)中;

    格式

    <!DOCTYPE RCC>
    <RCC version="1.0">
    <qresource prefix="/mainPage">
    <file>main.qml</file>
    <file alias = "images_bkg.png" >images/background.png</file>
    </qresource>
    </RCC>
    

    prefix是内置前缀, 不是实际目录名; alias可以帮助程序员将代码改动限制在qrc内;

    view.setSource(QUrl("qrc:/mainPage/main.qml"));
    

    QML使用:

    Image {
        source: "images_bkg.png"//"images/background.png" 
    }
    

    Note prefix会被带入到qml内的资源搜索路径中, 定义时需注意;
    系统资源不能从QML直接访问, 当QML文件被加载作为资源, 所有的文件指定在QML作为相对路径从系统资源载入.
    这种情况下在QML层访问系统资源是完全透明的. 但是当QML文件没有被加载作为资源, QML就无法访问系统资源;

    ---End---

    QML与Qt整合

    基于QWidget用户界面(把基于QWidget的程序导向QML不是个好主意)

    QDeclaractiveView是QWidget的子类;

    QDeclarativeView *qmlView = new QDeclarativeView;
    qmlView->setSource(QUrl::fromLocalFile("myqml.qml"));
    QWidget *widget = myExistingWidget();
    QVBoxLayout *layout = new QVBoxLayout(widget);
    widget->addWidget(qmlView);
    

    >缺点 QdeclarativeView初始化慢, 比QWidget占用更大内存, 如果创建大量QDeclarativeView对象会导致性能下降;
    这种情况下需要用QML重写QWidget, 从主QML部件载入qml来代替QDeclarativeView;

    QWidget UI是复杂的并且由少数静态页面组成的情况;
    QML UI是简单的并且由大量动态元素组成的情况;

    基于QGraphicsView的UI

    添加QML部件到一个QGraphicsScene; Graphics View Framework;

    QGraphicsScene* scene = myExistingGraphicsScene();
    QDeclarativeEngine *engine = new QDeclarativeEngine;
    QDeclarativeComponent component(engine, QUrl::fromLocalFile("myqml.qml"));
    QGraphicsObject *object = qobject_cast<QGraphicsObject *>(component.create());
    scene->addItem(object);
    

    >使用QDeclarativeComponent创建QGraphicsObject, QGraphicsScene::addItem()放置图形;

    Performance选项

    QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState)

    QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate)

    QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex)

    QML载入QGraphicsWidget对象

    使用qmlRegisterType();

    C++写QML扩展

    QtDeclarative模块提供API以便C++扩展QML; 添加QML类型, 扩展现有Qt, QML类型, 调用C++函数;

    Tips

    内置类型的转换: QColor - 字符串"red", QSize - 字符串 800*600

    继承自QDeclarativeItem, 覆盖paint()方法; 使用setParentItem()方法指定父级;

    qmlRegisterType()注册新的QML类型;

    Q_INVOKABLE 声明的方法可以被Qt metaObject系统和QML使用, slot函数也拥有相似的特性;

    Qt::transparent可以将颜色变为透明; 

    使用update()方法引发repaint;

    Q_ENUMS导出枚举类型;

    列表属性类型

    Q_PROPERTY(QDeclarativeListProperty<PieSlice> slices READ slices)
    QDeclarativeListProperty<PieSlice> slices();
    static void append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice);
    //...
    QDeclarativeListProperty<PieSlice> PieChart::slices()
    {
        return QDeclarativeListProperty<PieSlice>(this, 0, &PieChart::append_slice);
    }
    void PieChart::append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice)
    {
        PieChart *chart = qobject_cast<PieChart *>(list->object);
        if (chart) {
            slice->setParentItem(chart);
            chart->m_slices.append(slice);
        }
    }
    

    QML

    slices: [
    PieSlice {
        anchors.fill: parent
        color: "red"
        fromAngle: 0; angleSpan: 110
    },
    PieSlice {
        anchors.fill: parent
        color: "black"
        fromAngle: 110; angleSpan: 50}
    ]
    

    插件Plugin 

    作为QDeclarativeExtensionPlugin子类; Q_EXPORT_PLUGIN2宏定义;
    工程文件: 

    CONFIG += qt plugin;
    

    qmldir文件会被自动解析, 通知插件引擎载入; 

    plugin project-plugins lib
    

    ---End---

    refer to <QtQuick 中文手册>

  • 相关阅读:
    【数据库】事务,ACID,CAP和一致性
    线程,进程。多进程,多线程。并发,并行的区别
    mysql 集群 数据同步
    如何读取一个表的表类型,以及读取一个表中字段的类型.
    网络攻击技术开篇——SQL Injection
    MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?
    程序员找工作那些事(一)幸存者偏差
    程序员
    preg_replace的一些细节
    HDU 1258 Sum It Up(dfs 巧妙去重)
  • 原文地址:https://www.cnblogs.com/roymuste/p/3033265.html
Copyright © 2011-2022 走看看