zoukankan      html  css  js  c++  java
  • QML 从入门到放弃 第二卷

    第二卷如何更快速的放弃,注重的是C++和QML的交互

    <1>记事本。。

     

    (1) 先测试下不在QML创建C++对象,仅仅在main.cpp添加一个属性函数供调用. 注意只使用槽函数来做到。

    TextStreamLoader.h

    #ifndef TEXTSTREAMLOADER_H
    #define TEXTSTREAMLOADER_H
    
    #include <QObject>
    #include <QTextStream>
    #include <QDebug>
    class TextStreamLoader : public QObject
    {
        Q_OBJECT
    public:
        explicit TextStreamLoader(QObject *parent = 0);
        void test2(){qDebug()<<"test 2 without slots";}
    signals:
        void signal_readFile(QString buffer);
        void signal_error(QString errorMsg);
        void signal_saveFile(QString file,QString buffer);
    public slots:
        void slot_readFile(QString file);
        void slot_saveFile(QString file,QString buffer);
        void slot_test(){qDebug() << "test C++";}
        QString slot_getBuffer();
    
    private:
        QString _buffer;
    };
    
    #endif // TEXTSTREAMLOADER_H
    View Code

    TextStreamLoader.cpp

    #include "TextStreamLoader.h"
    #include <QFile>
    #include <QUrl>
    TextStreamLoader::TextStreamLoader(QObject *parent) : QObject(parent)
    {
        qDebug() << "Construct the TextStreamLoader";
        connect(this,&TextStreamLoader::signal_saveFile,
                this,&TextStreamLoader::slot_saveFile);
    }
    
    void TextStreamLoader::slot_readFile(QString file) // read a file to the _buffer
    {
    
        QUrl url(file);
        QString localFile = url.toLocalFile();
    
    
        QFile rfile(localFile);
        if(!rfile.open(QIODevice::ReadOnly))
        {
            QString errorMsg = "Could not open " + file + "
    ";
            qDebug() << errorMsg;
            emit signal_error(errorMsg);
            return ;
        }
    
        QTextStream in(&rfile);
        _buffer = in.readAll();
        emit signal_readFile(_buffer);
    
        rfile.close();
    
    }
    
    void TextStreamLoader::slot_saveFile(QString file, QString buffer)
    {
        QUrl url(file);
        QString localFile = url.toLocalFile();
        QFile wfile(localFile);
        if(!wfile.open(QFile::WriteOnly))
        {
            QString errorMsg = "Could not open " + localFile + "
    ";
            qDebug() <<errorMsg;
            emit signal_error(errorMsg);
            return ;
        }
    
        QTextStream out(&wfile);
        out << buffer;
        wfile.close();
    }
    
    QString TextStreamLoader::slot_getBuffer()
    {
        return _buffer;
    }
    View Code

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "TextStreamLoader.h"
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        QQmlContext *context = engine.rootContext();
    
    
        // 注意对象是在C++里构建
        TextStreamLoader stream_01;
        context->setContextProperty("stream_01",&stream_01);
        // 构建完C++对象
    
    
        // 加载我们的QML界面,只能调用槽函数
        qDebug() << "load the main.qml";
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        qDebug() <<engine.rootObjects()[0]->objectName();  // this will be debug "Houdini"
    
        return app.exec();
    }

    main.qml 用最简单的测试下我们的TextStreamLoader 里面的 "test()槽函数",一定要是槽函数才能被调用。

    main.qml全部都是通过调用C++的对象的槽函数,而C++对象是在main.cpp创建,所以在qml随时可以访问 槽函数。

    import QtQuick 2.6
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.1
    import QtQuick.Dialogs 1.2
    Window
    {
        id:root
        objectName: "Houdini"
        visible: true
         640
        height: 480
        title: qsTr("Hello World")
        color:"#202020"
        function loadTextToTextEdit(text)
        {
            textEdit.clear()
            var buffer = stream_01.slot_getBuffer()
            textEdit.append(buffer)
    
        }
        function saveTextToDisk(file,buffer)
        {
            stream_01.slot_saveFile(file,buffer)
        }
    
    
        Column
        {
            id:mainLayout
            padding: 5
            spacing: 10
            Row
            {
                id:buttonLayout
                spacing: 10
                Button
                {
                    id:loadButton
                    text:"load file"
                    highlighted: true
                    onClicked:
                    {
                        openDialog.open()
                    }
                }
                Button
                {
                    id:saveButton
                    highlighted: true
                    text:"save file"
                    onClicked:
                    {
                        saveDialog.open()
                    }
                }
    
            }
            Rectangle
            {
                height: 1
                 root.width
                id:menuRect
                color:"brown"
            }
    
            Flickable
            {
                id:flick
                 root.width; height: root.height;
                contentWidth: textEdit.paintedWidth
                contentHeight: textEdit.paintedHeight
                clip: true
                function ensureVisible(r)
                {
                    if (contentX >= r.x)
                        contentX = r.x;
                    else if (contentX+width <= r.x+r.width)
                        contentX = r.x+r.width-width;
                    if (contentY >= r.y)
                        contentY = r.y;
                    else if (contentY+height <= r.y+r.height)
                        contentY = r.y+r.height-height;
                }
                TextEdit
                {
                     flick.width
                    height: flick.height
                    anchors.margins: 10
                    focus: true
                    id:textEdit
                    text: ""
                    color:"brown"
                    font.family: "Helvetica"
                    font.pointSize: 10
                    font.bold: true
                    cursorVisible: true
                    selectByKeyboard: true
                    selectByMouse: true
                    wrapMode:TextEdit.WrapAnywhere
                    onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
    
                }
            }
    
    
        }
        FileDialog
        {
            id:openDialog
            title: "Please choose a file"
            folder: shortcuts.home
            onAccepted:
            {
                console.log("You chose: " + openDialog.fileUrls)
                stream_01.slot_readFile(openDialog.fileUrls)
                var buffer = stream_01.slot_getBuffer()
                loadTextToTextEdit(buffer)
    
            }
            onRejected:
            {
                console.log("Canceled")
            }
        }
        FileDialog
        {
            id:saveDialog
            title:"Save to a file"
            folder: shortcuts.home
            selectExisting : false
            onAccepted:
            {
                console.log("Save file : " + saveDialog.fileUrls)
                var text = textEdit.text;
                saveTextToDisk(saveDialog.fileUrl,text);
    
            }
            onRejected:
            {
                console.log("Canceled")
            }
    
        }
    
    }
    View Code

    (2)

    这次变化使用了QML里的connections.

    可以调用C++里的signal,signal带参数也可以传递过来。注意查看新的main.qml

     代码区别就是读取用的C++信号读取的。

    保存时用的信号在QML发射,然后调用C++的信号槽链接,来执行slot_saveFile()函数。

     main.qml:

    import QtQuick 2.6
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.1
    import QtQuick.Dialogs 1.2
    Window
    {
        id:root
        objectName: "Houdini"
        visible: true
         640
        height: 480
        title: qsTr("Hello World")
        color:"#202020"
        function loadTextToTextEdit(text)
        {
            textEdit.clear()
            var buffer = stream_01.slot_getBuffer()
            textEdit.append(buffer)
    
        }
        function saveTextToDisk(file,buffer)
        {
            stream_01.slot_saveFile(file,buffer)
        }
    
    
        Column
        {
            id:mainLayout
            padding: 5
            spacing: 10
            Row
            {
                id:buttonLayout
                spacing: 10
                Button
                {
                    id:loadButton
                    text:"load file"
                    highlighted: true
                    onClicked:
                    {
                        openDialog.open()
                    }
                }
                Button
                {
                    id:saveButton
                    highlighted: true
                    text:"save file"
                    onClicked:
                    {
                        saveDialog.open()
                    }
                }
    
            }
            Rectangle
            {
                height: 1
                 root.width
                id:menuRect
                color:"brown"
            }
    
            Flickable
            {
                id:flick
                 root.width; height: root.height;
                contentWidth: textEdit.paintedWidth
                contentHeight: textEdit.paintedHeight
                clip: true
                function ensureVisible(r)
                {
                    if (contentX >= r.x)
                        contentX = r.x;
                    else if (contentX+width <= r.x+r.width)
                        contentX = r.x+r.width-width;
                    if (contentY >= r.y)
                        contentY = r.y;
                    else if (contentY+height <= r.y+r.height)
                        contentY = r.y+r.height-height;
                }
                TextEdit
                {
                     flick.width
                    height: flick.height
                    anchors.margins: 10
                    focus: true
                    id:textEdit
                    text: ""
                    color:"brown"
                    font.family: "Helvetica"
                    font.pointSize: 10
                    font.bold: true
                    cursorVisible: true
                    selectByKeyboard: true
                    selectByMouse: true
                    wrapMode:TextEdit.WrapAnywhere
                    onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
    
                }
            }
    
    
        }
    
        Connections
        {
            target: stream_01
            onSignal_readFile://当读取文件的时候回触发这个信号
            {
                var readText = buffer //buffer是signal_readFile(buffer)参数
                textEdit.clear()
                textEdit.append(readText)
            }
        }
    
        // 读取文件的窗口
        FileDialog
        {
            id:openDialog
            title: "Please choose a file"
            folder: shortcuts.home
            onAccepted:
            {
                console.log("You chose: " + openDialog.fileUrl)
    
                //这句话会触发signal_readFile信号
                stream_01.slot_readFile(openDialog.fileUrl)
            }
            onRejected:
            {
                console.log("Canceled")
            }
        }
        //保存文件窗口
        FileDialog
        {
            id:saveDialog
            title:"Save to a file"
            folder: shortcuts.home
            selectExisting : false
            onAccepted:
            {
    
                console.log("Save file : " + saveDialog.fileUrl)
                var text = textEdit.text;
    
                //保存触发信号,在C++中这个信号会触发保存
                stream_01.signal_saveFile(saveDialog.fileUrl,text)
    
            }
            onRejected:
            {
                console.log("Canceled")
            }
    
        }
    
    }
    View Code

    (3)Q_PROPERTY宏,如果你想暴露一些member给QML对象。

    Q_OBJECT
    
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
    public:
        QString message(){return _msg;}
        void setMessage(QString msg)
    {
    _msg = msg;
    emit messageChanged();
    }

    类型如下:
    Q_PROPERTY(任意类型 QML访问属性名 READ 读取函数名 WRITE 写的函数名  NOTIFY 信号触发)

    <2>Q_INVOKABLE 宏,让QML可以随心所以调用函数。跟槽槽函数,信号一样调用。

    <3>在C++修改QML对象的属性,从C++call javaScript

     (1)修改qml root object的对象属性

    qDebug() <<engine.rootObjects()[0]->objectName();  // this will be debug "Houdini"
        QObject *root_object = engine.rootObjects().value(0); // houdini object ,it's the main object
    
        // set QML object property
        //root_object->setProperty("x",600);
        QQmlProperty::write(root_object, "x", 600);
    
        // read QML object property
        qDebug() << root_object->property("x").toInt();
        qDebug() << QQmlProperty::read(root_object,"x").toInt();
        
        // read root object child by name
        //QObject *rect = root_object->findChild<QObject*>("rect");
    View Code

     (2) 假如qml root object 有个java函数:

    function javefunctest(arg)
    {
         console.log(arg);
         return "I'm jave script"
    }

    C++访问:

    QObject *root_object = engine.rootObjects().value(0); // houdini object ,it's the main object
    QVariant firstArg("I am C++ arg");
    QVariant retValue;
    
        // call the jave script
    QMetaObject::invokeMethod(root_object,
                                  "javefunctest",
                                  Q_RETURN_ARG(QVariant,retValue),
                                  Q_ARG(QVariant,firstArg));
    
    qDebug() << "ret value is " << retValue;

    输出:

    qml: I am C++ arg

    ret value is QVariant(QString, "I'm java script")

    <4> EMCA:

    (1) 基本类型

    var flag =false //a boolean
    
    var x =1,y=2
    
    var str = 'abc' / "abc"
    
    var test = {x:2,y:3}
    
    console.log(test.x) //2
    
    console.log(test.y) //3
    
    test// object
    
    
    
    (1) typeof()类型 关键字
    
    To query the type of a variable, use the typeof keyword. typeof returns the name of the
    type as a string.
    
    var x=1;
    
    typeof(x) //"number"
    
    typeof {x:1} //'object '
    
    typeof typeof { x : 1 } // ’string’ 因为typeof()返回的是字符串.
    
    
    
    (2) 转换类型
    
    1.3333333.toFixed(2) // ’1.33’
    7..toString() // ’7’
    
    
    
    (3) 可以显式的把boolean ,number,string转换成对象:
    
    typeof 1. // ’number’
    typeof new Number(1.) // ’object’
    typeof new String(’Hi!’) // ’object’
    4)
    
    Objects themselves can be expressed using an array or object literal. Arrays have no separate
    type, but are specialized objects which use array indexes as properties:
    var o = { name: ’Werner’, age: 84 } // allocate simple object
    print(o.name, o[age])
    // both notations are valid, but [] notation allows generated strings
    var a = [’a’, ’b’, 7, 11.]
    // an array, equivalent to {’0’: ’a’, ’1’: ’b’, ’2’: 7, ’3’: 11.}
    typeof o, a // ’object’, ’object’
    View Code

    (2)函数

    函数:所有的函数都会evaluates to something:

    function f() {} //evaluates as 'undefined'

    function f() {} +1 // evaluates as 1 ,because 'undefined' is casted to 0

    (function f() {}) //evaluates to a function object

    (function () {return 0;}) () /evaluates as 0

     (3)

    for loop :

    i 作为了index

     (4)

     

    delete p.z // remove p.z

    p.z //undefined

     (5)在列表中存入,或者在json对象中存在函数

    (6) 创建对象new关键字

    (1)

     

    (2)创建对象默认构造函数:

    这个时候Point其实就是个类。

     为Point类添加个函数.

    Each function in JavaScript can be used as a constructor in combination with the new operator.
    To support inheritance, each function has a default property named prototype. Objects
    created from a constructor inherit all properties from the constructor’s prototype. Consider the
    following example:

     其实 prototype里面的方法属于派生出来的,如何检查一个方法,或者一个类对象是原有的:

     

     <2>公司一个小项目

    按钮效果模仿的是Google material design风格。流动起来。参考上篇有详细代码.

    V2:

    3,CG Browser

    New Version:0.00001

  • 相关阅读:
    DL/T 467-2019 电站磨煤机及制粉系统性能试验
    fidlder-05(拦截并修改数据)
    fiddler-04(怎么对APP抓包)
    Redis5设计与源码分析读后感(二)简单动态字符串SDS
    Jedis连接搭建在阿里云服务器上的Redis,基于Linux(CentOS7)
    centos7下安装redis6.0版本+3种启动方式
    Linux下端口被占用的解决方法
    Linux卸载Nginx
    linux中普通用户修改密码出现(passwd:Authentication token manipulation error)
    linux重置密码提示与用户名相似该怎么解决?
  • 原文地址:https://www.cnblogs.com/gearslogy/p/6664238.html
Copyright © 2011-2022 走看看