QML与C++交互



  • QML与c++交互学习笔记(一)

    说明,主要是对QT的文档内例子进行的一些分别解说,希望更容易的理解

    C++导出到QML的过程。

    1.导出一个简单的类Person

    2.具体导出过程

    假设我们要导出一个Person类,

     A 那么就要考虑如何的一个类他才可以导出呢?
    
     他需要符合一定的条件
    
    1.继承自QObject
    
    2.有默认构造函数
    
    
    
     B 如何导出呢?
    
          通过一个函数
    
          int qmlRegisterType(const char *uri,int versionMajor, int versionMinor, const char *qmlName)
    
          int qmlRegisterType()
    

    3.具体的例子

    // person.h

    #ifndef PERSON_H  
    #define PERSON_H  
    #include <QObject>  
    class Person : public QObject  
    {  
        Q_OBJECT  
    public:  
        explicit Person(QObject *parent = 0);  
    };  
    #endif // PERSON_H  
       
    // person.cpp  
    #include "person.h"  
    Person::Person(QObject *parent) :  
        QObject(parent)  
    {  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include "person.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        qmlRegisterType<Person>("People",1,0,"Person");  
        //qmlRegisterType<Person>();  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    import People 1.0 //如果是qmlRegisterType<Person>(); 导出就可以注释这条

    Rectangle {

    width: 640
    
    height: 480
    
    Person{}
    

    }

    说明:我们通过qmlRegisterType<Person>("People",1,0,"Person");

    向QML中导出Person类,这个类在People包中,在QML中需要使用Person类的

    话就必须包含People包,通过import People 1.0来包含,之后就可以使用Person

    创建对象使用来。

    QML与c++交互学习笔记(二)

    1.导出Person类中的成员方法

    2.具体导出过程

    导出的方法有
    
    1.使用Q_INVOKABLE
    
    2.使用 槽机制
    

    3.具体代码

    // person.h

    #ifndef PERSON_H  
    #define PERSON_H  
    #include <QObject>  
    class Person : public QObject  
    {  
        Q_OBJECT  
    public:  
        explicit Person(QObject *parent = 0);  
        Q_INVOKABLE void FirstEcho(void);  
    public slots:  
        void SecondEcho(void);  
    };  
    #endif // PERSON_H  
    

    // person.cpp

    #include "person.h"  
    Person::Person(QObject *parent) :  
        QObject(parent)  
    {  
    }  
    void Person::FirstEcho(void)  
    {  
        // 简简单单打印一句话  
        qDebug("call Person::FirstEcho");  
    }  
    void Person::SecondEcho(void)  
    {  
        qDebug("call Person::SecondEcho");  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include "person.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        qmlRegisterType<Person>("People",1,0,"Person");  
        //qmlRegisterType<Person>();  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    import People 1.0 //如果是qmlRegisterType<Person>(); 导出就可以注释这条

    Rectangle {

    width: 640
    
    height: 480
    
    Person{ id: per;}
    
    MouseArea{
    
        anchors.fill: parent;
    
        onClicked:{
    
            per.FirstEcho();
    
            per.SecondEcho();
    
        }
    
    }
    

    }

    说明:

    这里导出了两个函数分别是FirstEcho 和SecondEcho 两个函数,这两个函数本别是使用
    

    FirstEcho使用使用 Q_INVOKABLE导出,SecondEcho直接使用槽。

    调用函数在控制台输出一些信息,这里是在鼠标点击界面后出发的。

    QML与c++交互学习笔记(三)

    1.导出Person类中的属性

    2.具体导出过程

    1.导出Person一个颜色属性,一个int属性
    
    注意
    
    1. 当需要实现属性变化其他引用到此属性的属性也跟着变化的情况的话,需要设置属性相应的信号
    
    2. 设置属性的时候,使用的类型必须是已经导出到QML中的类型
    

    3.具体代码

    // person.h

    #ifndef PERSON_H  
    #define PERSON_H  
    #include <QObject>  
    #include <QColor>  
    class Person : public QObject  
    {  
        Q_OBJECT  
        // 设置设置属性的名字是 bgcolor  
        // 对应读取函数名字 bgColor  
        // 对应写函数名字 setBgColor  
        // 属性发生改变后发送信号 sendBgColorChange  
        Q_PROPERTY(QColor bgcolor READ getBgColor WRITE setBgColor NOTIFY sendBgColorChange)  
       // 设置设置属性的名字是 count  
       // 对应读取函数名字 getCount  
       // 对应写函数名字 setCount  
       // 属性发生改变后发送信号 sendCountChange  
       Q_PROPERTY(int count READ getCount WRITE setCount NOTIFY sendCountChange)  
    public:  
        explicit Person(QObject *parent = 0);  
        QColor getBgColor(void) const;  
        void setBgColor(const QColor& color);  
        int getCount(void);  
        void setCount(int count);  
    signals:  
        void sendBgColorChange(void);  
        void sendCountChange(void);  
    private:  
        QColor  m_Color;  
        int     m_Count;  
    };  
    #endif // PERSON_H  
    

    // person.cpp

    #include "person.h"  
    //---------------------------------  
    //  
    Person::Person(QObject *parent) :  
        QObject(parent), m_Color("blue"), m_Count(0)  
    {  
    }  
    //---------------------------------  
    //  
    QColor Person::getBgColor(void) const  
    {  
        return m_Color;  
    }  
    //---------------------------------  
    //  
    void Person::setBgColor(const QColor& color)  
    {  
        m_Color = color;  
        emit sendBgColorChange();  
    }  
    //---------------------------------  
    //  
    int Person::getCount(void)  
    {  
        return m_Count;  
    }  
    //---------------------------------  
    //  
    void Person::setCount(int count)  
    {  
        m_Count = count;  
        emit sendCountChange();  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include "person.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        qmlRegisterType<Person>("People",1,0,"Person");  
        //qmlRegisterType<Person>();  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    import People 1.0 //如果是qmlRegisterType<Person>(); 导出就可以注释这条

    Rectangle {

    width: 640
    
    height: 480
    
    color: per.bgcolor;
    
    Person{ id: per;}
    
    Text {
    
        id: textlabel;
    
        text: "text  " + per.count;
    
    }
    
    MouseArea{
    
        anchors.fill: parent;
    
        onClicked:{
    
            // 当鼠标按下后,由于属性上有信号,当属性发生改变后,
    
            // 所有引用此属性的值的都相应的发生改变
    
            per.bgcolor = "red";
    
            per.count = 20;
    
        }
    
    }
    

    }

    说明:

    在person类中,设置了两个属性bgcolor,count ,他们分别在发送改变后调用自己对应的信号
    

    具体看源代码,这里是设置来矩形框的颜色,文本框中文本。

    QML与c++交互学习笔记(四)

    1.导出Person类,并且一个Job类,Job类包含一个Person的指针

    2.具体导出过程

    1.通过属性来实现,具体的请看代码
    

    3.具体代码

    // person.h

    #ifndef PERSON_H  
    #define PERSON_H  
    #include <QObject>  
    #include <QColor>  
    class Person : public QObject  
    {  
        Q_OBJECT  
        // 设置设置属性的名字是 name  
        // 对应读取函数名字 getName  
        // 对应写函数名字 setName  
        // 属性发生改变后发送信号 sendNameChange  
        Q_PROPERTY(QString name READ getName WRITE setName NOTIFY sendNameChange)  
       // 设置设置属性的名字是 age  
       // 对应读取函数名字 getAge  
       // 对应写函数名字 setAge  
       // 属性发生改变后发送信号 sendAgeChange  
       Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY sendAgeChange)  
    public:  
        explicit Person(QObject *parent = 0);  
        QString getName(void) const;  
        void setName(const QString& name);  
        int getAge(void);  
        void setAge(int age);  
    signals:  
        void sendNameChange(void);  
        void sendAgeChange(void);  
    private:  
        QString     m_Name;  
        int         m_Age;  
    };  
    /* 
     设想一份工作给予一个人 
     */  
    class Job : public QObject  
    {  
        Q_OBJECT  
        Q_PROPERTY(Person *per READ getPerson WRITE setPerson NOTIFY sendPersonChange)  
        Q_PROPERTY(QString jn READ getJobName WRITE setJobName NOTIFY sendJobNameChange)  
    public:  
        explicit Job(QObject *parent = 0);  
        ~Job();  
        void setPerson(Person *per);  
        Person *getPerson(void) const;  
        void setJobName(const QString & jobname);  
        QString getJobName(void) const;  
    signals:  
        void sendPersonChange();  
        void sendJobNameChange();  
    private:  
        Person *m_Person;  
        QString m_JobName;  
    };  
    #endif // PERSON_H  
    

    // person.cpp

    #include "person.h"  
    //---------------------------------  
    //  
    Person::Person(QObject *parent) :  
        QObject(parent), m_Name("unknow"), m_Age(0)  
    {  
    }  
    //---------------------------------  
    //  
    QString Person::getName(void) const  
    {  
        return m_Name;  
    }  
    //---------------------------------  
    //  
    void Person::setName(const QString& name)  
    {  
        m_Name = name;  
        emit sendNameChange();  
    }  
    //---------------------------------  
    //  
    int Person::getAge(void)  
    {  
        return m_Age;  
    }  
    //---------------------------------  
    //  
    void Person::setAge(int age)  
    {  
        m_Age = age;  
        emit sendAgeChange();  
    }  
    //---------------------------------  
    //  
    Job::Job(QObject *parent)  
        :QObject(parent), m_Person(0), m_JobName("unknown")  
    {  
    }  
    //---------------------------------  
    //  
    Job::~Job()  
    {  
    }  
    //---------------------------------  
    //  
    void Job::setPerson(Person *per)  
    {  
        m_Person = per;  
        emit sendPersonChange();  
    }  
    //---------------------------------  
    //  
    Person *Job::getPerson(void) const  
    {  
        return m_Person;  
    }  
    //---------------------------------  
    //  
    void Job::setJobName(const QString & jobname)  
    {  
        m_JobName = jobname;  
        emit sendJobNameChange();  
    }  
    //---------------------------------  
    //  
    QString Job::getJobName(void) const  
    {  
        return m_JobName;  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include "person.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        qmlRegisterType<Person>("People",1,0,"Person");  
        //qmlRegisterType<Person>();  
        qmlRegisterType<Job>("People",1,0,"Job");  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    import People 1.0 //如果是qmlRegisterType<Person>(); 导出就可以注释这条

    Rectangle {

    width: 640
    
    height: 480
    
    Job {
    
        id: jobA;
    
        jn: "Learn";
    
        per: Person { id: ps; name: "Luly"; age: 25; }
    
    }
    
    // 显示这份工作的一些信息
    
    Rectangle{
    
        x: 100; y: 100;
    
        width: 100; height: 100;
    
        Text { text: "Job name:" + jobA.jn; }
    
        Text { y: 20; text: "Person name:" + ps.name; }
    
        Text { y: 40; text: "Person age:"  + ps.age; }
    
    }
    
    MouseArea{
    
        anchors.fill: parent;
    
        onClicked:{
    
            // 我要改变工作的名字 工作人的信息
    
            jobA.jn = "Clean House";
    
            ps.name = "Tom";
    
            ps.age = 30;
    
        }
    
    }
    

    }

    说明:

    主要是导出了两个类Person和Job, Job 包含一个Person的指针,这样后,可以看到
    

    在QML中,我们需要给予Job对象一个Person来尽心赋值。

    QML与c++交互学习笔记(五)

    1.导出Person类,并且一个PersonGroup类,PersonGroup类是Person的一个组

    2.具体导出过程

    1.通过属性来实现,具体的请看代码
    

    3.具体代码

    // person.h

    #ifndef PERSON_H  
    #define PERSON_H  
    #include <QObject>  
    #include <QDeclarativeListProperty>  
    #include <QList>  
    class Person : public QObject  
    {  
        Q_OBJECT  
        Q_PROPERTY(QString name READ getName WRITE setName NOTIFY sendNameChange)  
        Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY sendAgeChange)  
    public:  
        explicit Person(QObject *parent = 0);  
        QString getName(void) const;  
        void setName(const QString& name);  
        int getAge(void);  
        void setAge(int age);  
    signals:  
        void sendNameChange(void);  
        void sendAgeChange(void);  
    private:  
        QString     m_Name;  
        int         m_Age;  
    };  
    class PersonGroup : public QObject  
    {  
        Q_OBJECT  
        Q_PROPERTY(QDeclarativeListProperty<Person> members READ members)  
    public:  
        explicit PersonGroup(QObject *parent = 0);  
        QDeclarativeListProperty<Person> members(void);  
        Q_INVOKABLE int membersCount(void) const;  
        Q_INVOKABLE Person *member(int index) const;  
    private:  
        QList<Person*> m_MemberList;  
    };  
    #endif // PERSON_H  
    

    // person.cpp

    #include "person.h"  
    //---------------------------------  
    //  
    Person::Person(QObject *parent) :  
        QObject(parent), m_Name("unknow"), m_Age(0)  
    {  
    }  
    //---------------------------------  
    //  
    QString Person::getName(void) const  
    {  
        return m_Name;  
    }  
    //---------------------------------  
    //  
    void Person::setName(const QString& name)  
    {  
        m_Name = name;  
        emit sendNameChange();  
    }  
    //---------------------------------  
    //  
    int Person::getAge(void)  
    {  
        return m_Age;  
    }  
    //---------------------------------  
    //  
    void Person::setAge(int age)  
    {  
        m_Age = age;  
        emit sendAgeChange();  
    }  
    //---------------------------------  
    //  
    PersonGroup::PersonGroup(QObject *parent)  
        :QObject(parent)  
    {  
    }  
    //---------------------------------  
    //  
    QDeclarativeListProperty<Person> PersonGroup::members(void)  
    {  
        return QDeclarativeListProperty<Person>(this, m_MemberList);  
    }  
    //---------------------------------  
    //  
    int PersonGroup::membersCount() const  
    {  
        return m_MemberList.size();  
    }  
    //---------------------------------  
    //  
    Person *PersonGroup::member(int index) const  
    {  
        return m_MemberList.at(index);  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include "person.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        qmlRegisterType<Person>("People",1,0,"Person");  
        //qmlRegisterType<Person>();  
        qmlRegisterType<PersonGroup>("People",1,0,"PersonGroup");  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    import People 1.0 //如果是qmlRegisterType<Person>(); 导出就可以注释这条

    Rectangle {

    width: 640
    
    height: 480
    
    property int pgcurIndex: 0;
    
    PersonGroup{
    
        id: group;
    
        members: [
    
            Person { name: "A"; age: 20},
    
            Person { name: "B"; age: 21},
    
            Person { name: "C"; age: 22},
    
            Person { name: "D"; age: 23},
    
            Person { name: "E"; age: 24}
    
        ]
    
    }
    
    // 显示这份工作的一些信息
    
    Rectangle{
    
        x: 100; y: 100;
    
        width: 100; height: 100;
    
        Text { id: text1;  text: ""}
    
        Text { id: text2;  y: 20; text: ""}
    
        Text { id: text3;  y: 40; text: ""}
    
    }
    
    MouseArea{
    
        anchors.fill: parent;
    
        onClicked:{
    
            //if (pgcurIndex < group.membersCount() - 1){ // 这里两种方法都可以
    
            if (pgcurIndex < group.members.length - 1){
    
                pgcurIndex++;
    
            }else{
    
                pgcurIndex = 0;
    
            }
    
            // 显示信息
    
            text1.text = "PersonGroup index: " + pgcurIndex;
    
            var person = group.member(pgcurIndex);
    
            text2.text = "Person name: " + person.name;
    
            text3.text = "Person age: "  + person.age;
    
        }
    
    }
    

    }

    说明:

    这里导出了两个类Person, PersonGroup, PersonGroup保存来一个Person的组,
    

    我们通过导出的函数来调用类面的成员,获取成员的信息.

    QML与c++交互学习笔记(六) 关于qt c++中创建对象,QML获取此对象数据问题

    1.假设

    1.在c++中创建一个Person的对象,
    
    2.在QML中获取并显示数据
    
    3.在c++中改变数据后,显示的数据能进行相应的改变
    
    
    
    也就是说我们实际是在c++中new一个对象出来,而把这个对象的数据在QML里面进行显示
    

    2.具体代码

    // person.h

    #ifndef PERSON_H  
    #define PERSON_H  
    #include <QObject>  
    #include <QDeclarativeListProperty>  
    #include <QList>  
    #include <QColor>  
    class Person : public QObject  
    {  
        Q_OBJECT  
        Q_PROPERTY(QString name READ getName WRITE setName NOTIFY sendNameChange)  
        Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY sendAgeChange)  
    public:  
        explicit Person(QObject *parent = 0);  
        QString getName(void) const;  
        void setName(const QString& name);  
        int getAge(void);  
        void setAge(int age);  
        // 一个简单的函数, 获取蓝色  
        Q_INVOKABLE QColor getColor(void) const;  
        Q_INVOKABLE void changeNameAndAge(void);  
    signals:  
        void sendNameChange(void);  
        void sendAgeChange(void);  
    private:  
        QString     m_Name;  
        int         m_Age;  
    };  
    #endif // PERSON_H  
    

    // person.cpp

    #include "person.h"  
    //---------------------------------  
    //  
    Person::Person(QObject *parent) :  
        QObject(parent), m_Name("unknow"), m_Age(0)  
    {  
    }  
    //---------------------------------  
    //  
    QString Person::getName(void) const  
    {  
        return m_Name;  
    }  
    //---------------------------------  
    //  
    void Person::setName(const QString& name)  
    {  
        m_Name = name;  
        emit sendNameChange();  
    }  
    //---------------------------------  
    //  
    int Person::getAge(void)  
    {  
        return m_Age;  
    }  
    //---------------------------------  
    //  
    void Person::setAge(int age)  
    {  
        m_Age = age;  
        emit sendAgeChange();  
    }  
    //---------------------------------  
    //  
    QColor Person::getColor(void) const  
    {  
        return QColor(Qt::blue);  
    }  
    //---------------------------------  
    //  
    void Person::changeNameAndAge(void)  
    {  
        setName("Luly");  
        setAge(31);  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include <QtDeclarative/QDeclarativeContext>  
    #include "person.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        Person tmpPerson;  
        tmpPerson.setName("Tom");  
        tmpPerson.setAge(25);  
        QDeclarativeView qmlView;  
        qmlView.rootContext()->setContextProperty("ps",&tmpPerson);  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    Rectangle {

    width: 640
    
    height: 480
    
    Text { text: "Person name:" + ps.name; }
    
    Text { y: 20; text: "Person age:" + ps.age; }
    
    Rectangle{ x: 20; y: 40;  width: 20; height: 20; color: ps.getColor();}
    
    MouseArea{
    
        anchors.fill: parent;
    
        // 当鼠标按下后改变名字和年龄
    
        onClicked: { ps.changeNameAndAge(); }
    
    }
    

    }

    说明:

    我们在c++中创建来一个对象,并且在把这个对象导出给QML调用用,我们设置来属性,QML中可以直接使用属性来进行赋值.
    

    QML与c++交互学习笔记(七)

    1.假设这样一种情况

    我这里由一个Wideget 继承自QWidget上面添加来一个QLabel, 一个QPushButton
    
    我如何把这个Wideget放到QML中使用,那么我当QPushButton 按下后我怎么在QML中进行处理呢?
    
    我这里指出一种方法
    
       让Wideget 继承QGraphicsProxyWidget,对Wideget进行导出,在QML中创建
    

    此对象,在他导出的信中进行处理,具体代码。

    还有就是这个网址上说明来很多QML与c++之间通讯的方法,很悲剧的是我的assistant中却没有者部分,不知道版本低还是怎么的。
    

    http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html

    2.具体代码

    //widget.h

    #ifndef WIDGET_H  
    #define WIDGET_H  
    #include <QWidget>  
    #include <QGraphicsProxyWidget>  
    #include <QPushButton>  
    #include <QLabel>  
    #include <QLineEdit>  
    class Widget : public QGraphicsProxyWidget  
    {  
        Q_OBJECT  
    public:  
        explicit Widget(QGraphicsItem *parent = 0);  
        ~Widget();  
        Q_INVOKABLE void changeText(const QString& s);  
    signals:  
        void sendOnButton(void);  
    private:  
        QPushButton *m_Btn;  
        QLabel      *m_Label;  
        QWidget     *m_MainWidget;  
    };  
    #endif // WIDGET_H  
    

    //widget.cpp

    #include "widget.h"  
    Widget::Widget(QGraphicsItem *parent) :  
        QGraphicsProxyWidget(parent)  
    {  
        m_MainWidget = new QWidget;  
        m_Btn = new QPushButton(m_MainWidget);  
        m_Label = new QLabel(m_MainWidget);  
        m_Btn->setText("PushButton");  
        m_Btn->setGeometry(10, 10, 100, 30);  
        m_Label->setGeometry(10, 40, 200, 30);  
        QObject::connect(m_Btn, SIGNAL(clicked()), this, SIGNAL(sendOnButton()));  
        setWidget(m_MainWidget);  
    }  
    Widget::~Widget()  
    {  
        delete m_MainWidget;  
    }  
    void Widget::changeText(const QString& s)  
    {  
        m_Label->setText(s);  
        qDebug(" call Widget::changeText");  
    }  
    

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include <QtDeclarative/QDeclarativeContext>  
    #include "widget.h"  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        qmlRegisterType<Widget>("UIWidget", 1, 0, "Widget");  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        return a.exec();  
    }  
    

    // UICtest.qml

    import Qt 4.7

    import UIWidget 1.0

    Rectangle {

    width: 640
    
    height: 480
    
    color: "black"
    
    Widget { id: uiwidget; x: 100; y: 100; width: 400; height: 100;
    
        // 关键在这里,当一个信号导出后他的相应的名字就是第1个字母大写,前面在加上on
    
        // 例如 clicked -- onClicked   colorchange --onColorchange;
    
        onSendOnButton: { uiwidget.changeText(textinput.text); }
    
    }
    
    Rectangle{
    
        x: 100; y: 20; width: 400; height: 30;  color: "blue"
    
        TextInput {id: textinput; anchors.fill: parent; color: "white" }
    
    }
    

    }

    说明:

    这里实现的是当QPushButton按钮按下后,获取QML中TextInput上的文本,
    

    对QLabel进行设置,关键点在于Widget中的信号函数sendOnButton, 他导出后在QML中

    将引发的是onSendOnButton只要在QML中对这个编写处理就可以实现,具体看代码。

    QML与c++交互学习笔记(八) qtc++直接调用QML中的函数, 直接设置属性

    1.这里主要是介绍,如何在c++中调用QML中的函数和设置QML中的属性的问题

    2.具体代码

    // UICtest.qml

    import Qt 4.7

    Rectangle {

    id: mainWidget;
    
    width: 640
    
    height: 480
    
    function callbyc(v)
    
    {
    
        mainWidget.color = v;
    
        return "finish";
    
    }
    
    Rectangle{
    
        id: secondRect;
    
        x: 100;
    
        y: 20;
    
        width: 400;
    
        height: 300;
    
        Rectangle{
    
            x: 10;
    
            y: 20;
    
            width: 30;
    
            height: 40;
    
            color: "#FF035721"
    
            Text  {
    
                objectName: "NeedFindObj";
    
                anchors.fill: parent;
    
                text: "";
    
            }
    
        }
    
    }
    

    }

    // main.cpp

    #include <QtGui/QApplication>  
    #include <QtDeclarative/QDeclarativeView>  
    #include <QtDeclarative/QDeclarativeEngine>  
    #include <QtDeclarative/QDeclarativeComponent>  
    #include <QtDeclarative/QDeclarativeContext>  
    #include <QtDeclarative/QDeclarativeItem>  
    #include <QMetaObject>  
    int main(int argc, char *argv[])  
    {  
        QApplication a(argc, argv);  
        QDeclarativeView qmlView;  
        qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));  
        qmlView.show();  
        // 获取根节点,就是 QML中 id是mainWidget的节点  
        QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(qmlView.rootObject());  
        item->setProperty("color", QVariant("blue"));  
        // 查找到我们需要的节点根均objectname NeedFindObj 来获得,并设置他的文本属性  
        QDeclarativeItem *item1 = item->findChild<QDeclarativeItem *>("NeedFindObj");  
        if (item1)  
        {  
            item1->setProperty("text", QVariant("OK"));  
        }  
        // 调用QML中的函数, 分别是 函数所在的对象, 函数名,返回值, 参数  
        QVariant returnVar;  
        QVariant arg1 = "blue";  
        QMetaObject::invokeMethod(item, "callbyc",  
                                  Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1));  
        qDebug(" %s",returnVar.toString().toLocal8Bit().data());  
        return a.exec();  
    }  
    

    说明:

    这里的根节点是id为mainWidget的矩形元素,那么在C++中获取根节点后就可以,直接的设置他的属性了。其他属性也可以同样,调用指定节点内的函数是通过QMetaObject中的invokeMethod 来进行调用的。


  • 嗯,是好文章呢。可不可以将它放在博客区呢?



  • ...Nice...



  • 好东西,交互我一直不懂,马了等不忙再看



  • @_Inky 对了,如果是Qt 5,具体来说是Qt 5.1以后,那么这么写是不能通过的。很多地方都要换成QQuick*。import Qt 4.7 ——Qt 5以后的版本使用的是import QtQuick 2.5



  • 问个问题,我在widget生成的界面中调用qml生成的界面;采用qtquick1.0,通过declarative可以正常显示;不过目前我要使用qtquick2.0,调用中提示Can't find surface 2 ,版主知道什么原因不?O(∩_∩)O谢谢

    注:在main.cpp中直接调用qml无论qtquick是1.0还是2.0都可以正常显示。
    0_1451025835488_upload-595f92da-63b9-4ac8-aca6-9a9a3af17476



  • @Eli 这个view的Parent设置为mainWindow的指针试试看?



  • @jiangcaiyang 你好楼主,有没有办法在c++导出的类型中写入qml基本组件,例如写一个Rectangle,我写完它不显示,因为之前做的东西里他们就是这么写的可现在我自己实现不会写了感觉。例如笔记一里你导出了Person类,然后在qml中直接写Person{
    Rectangle{}
    }// 有没有可以这样写的方法。



  • @jiangcaiyang 😐 谢谢指正


Log in to reply
 

走马观花

最近的回复

  • H

    hi 有问题请教你,方便加个联系方式吗

    read more
  • boost.asio是一个很棒的网络库,这回儿我也开始系统地学习起来了。想想当年接触boost,也有八年多了。这次开始接触boost,觉得既熟悉又陌生。熟悉的是小写字母+下划线的命名方式、晦涩的模板、很慢的编译速度以及较大的程序体积,陌生的是asio的各种概念:io服务、接收器、套接字等等:我之前对网络编程不是非常了解。

    于是根据我的理解,参考《Boost.Asio C++网络编程》实现了这样一个简单的客户端和服务端通信的例子,例子非常简单,还不完善,但是幸运的是,可以在本机上互通了。
    下面是客户端的代码:

    #include <iostream> #include <boost/asio.hpp> #include <boost/proto/detail/ignore_unused.hpp> using namespace std; using namespace boost::asio; using namespace boost::system; using namespace boost::proto::detail;// 提供ignore_unused方法 void writeHandler( const boost::system::error_code& ec, size_t bytesTransferred ) { if ( ec ) { cout << "Write data error, code: " << ec.value( ) << "transferred: " << bytesTransferred << endl; } else { cout << "OK! " << bytesTransferred << "bytes written. " << endl; } } int main(int argc, char *argv[]) { ignore_unused( argc ); ignore_unused( argv ); io_service service; ip::tcp::socket sock( service ); ip::tcp::endpoint ep( ip::address::from_string( "127.0.0.1" ), 6545 ); boost::system::error_code ec; sock.connect( ep, ec ); if ( ec ) { cout << "Connect error, code: " << ec.value( ) << ", We will exit." << endl; return ec.value( ); } else { char buf[1024] = "Hello world!"; sock.async_write_some( buffer( buf ), writeHandler ); sock.close( ); } return service.run( ); }

    下面是服务端的代码:

    #include <iostream> #include <boost/asio.hpp> #include <boost/proto/detail/ignore_unused.hpp> using namespace std; using namespace boost::asio; using namespace boost::system; using namespace boost::proto::detail;// 提供ignore_unused方法 void acceptHandle( const boost::system::error_code& code ) { cout << "Accepted." << endl; } int main(int argc, char *argv[]) { ignore_unused( argc ); ignore_unused( argv ); io_service service; ip::tcp::endpoint ep( ip::address::from_string( "127.0.0.1" ), 6545 ); boost::system::error_code ec; ip::tcp::socket sock( service ); ip::tcp::acceptor acceptor( service, ep ); acceptor.async_accept( sock, acceptHandle ); if ( ec ) { cout << "There is an error in server. code: " << ec.value( ) << endl; } return service.run( );// 阻塞运行 }

    运行结果是这样的:
    78448d7b-b3ae-42fc-9e2e-4dd2fbdac2c2-image.png

    我对boost.asio中几个概念的理解:

    io_service,这就是一个类似事件循环的东西,它为io设备提供服务,故名。不管是套接字、文件还是串口设备,都要使用它的服务。它的run()函数相当于启动了一个事件循环。一旦有消息了,即进行响应。这也是实现异步编程的重要基础。 socket,这个类则是套接字,可以处理TCP或者是UDP请求。有同步以及异步的处理方式,也有带异常以及不带异常的处理方式。 acceptor,接收器,仅仅是服务端使用。相当于其余框架中的listener,作接收用的。

    比较浅显,如果有不当之处,敬请指正。

    read more
  • 843143141.jpg
    闲下来了,我又开始大规模地学习了。
    最近开始学习内存模型和无锁结构。因为这个是和操作系统密切相关的,懂得这些对于编写C++服务端应用程序
    有着非常好的帮助。之前我对内存模型以及无锁结构几乎没有什么了解,我就询问群里的大佬看看有没有可以参考的资料。
    大佬很高兴,并且推荐了我一本名为《Memory Model》的电子书。这本电子书虽然页数不多,但是从起源到发展,
    从源码到汇编,都给我们详细地介绍了。看了一遍,不是非常理解,但是依然尝试将自己的理解写下来,以便日后翻阅。
    首先因为多核处理器成为主流,多线程的程序已经非常常见,因此我们不可避免地要处理多线程程序的同步问题。
    然后,因为编译器默认都对源码进行了优化,在单核处理器中这通常不是什么问题,但是在多核处理器中,就会因为编译器
    对其进行了乱序处理而导致程序出现问题。由此深入地探讨内存模型。
    内存模型主要分为:
    载-载 顺序(load-load order)
    载-存 顺序(load-store order)
    存-载 顺序(store-load order)
    存-存 顺序(store-store order)
    依赖载入顺序(dependent loads order)

    通过内存栅栏(memory barrier)能够避免编译器对指令的乱序。Linux中有

    READ_ONCE( x, value ) WRITE_ONCE( x )

    避免这些读写被编译器乱序或者是优化掉。

    这里谈到volatile关键字。在另外一篇博客上说,volatile具有“易变性、不可优化性、顺序性”。简单说,由于
    被volatile声明的变量,指令须从内存读取,并且不能被编译器乱序以及优化。在Java(语言扩展)和MSVC(系统兼容)上,
    还附带了Accquire()和Release()语义,因此可部分用于多线程环境。但多数情况下,还是慎用volatile,
    因为不同架构的处理器,它的内存模型是千变万化的,不能一而概之。

    至于C++11,它提供了std::atomic<T>这个模板类,相当于提供了很多方式来实现不同内存模型的原子操作。
    它的load()和store()方法,第二个参数有以下几个选项:

    std::memory_order_relaxed std::memory_order_seq_cst std::memory_order_acq_rel std::memory_order_acquire std::memory_order_release std::memory_order_consume

    我们最常用来实现RCpc(Release Consistency、Processor Consistency)是使用

    std::memory_order_acquire std::memory_order_release

    这两对。

    作为例子,在实现自旋锁时使用std::atomic<T>是这样的:

    struct SpinLock2 { void lock( ) { for ( ; ; ) { while ( lock_.load( std::memory_order_relaxed ) ); if ( !lock_.exchange( true, std::memory_order_acquire ) ) break; } } void unlock( ) { lock_.store( false, std::memory_order_release ); } std::atomic<bool> lock_ = { false }; };

    read more
  • 113.jpg
    1、什么是lambda表达式,什么是闭包?
    lambda表达式即lambda函数,也就是匿名函数。

    lambda表达式在C++中包含了
    []表示捕获
    ()是函数的参数,需要指定类型
    ->type是返回的类型,可以省略,如果编译器无法推出类型的话可以强制编写
    {}是函数体。

    lambda可以被声明为mutable的,作用是将捕获的内容进行改变。
    闭包是函数的定义以及定义函数时提供的环境,总称为闭包。lambda函数也是一种闭包。
    lambda本身是匿名函数,而捕获语句则是提供了定义函数时提供的环境。

    2、什么是右值引用?
    右值引用相对与左值引用而言的。左值即=运算符左边的变量,右值是=运算符右边的常量或变量。由此可以看出,
    右值引用指的是对常量或变量的引用。它的用途包含了移动语义和完美转发。
    移动语义就是弥补了C++历史在处理变量传递时丢失的一种语义。它和值传递、引用传递一样,是变量传递的方式之一。
    如果没有移动语义,为了将一个类的实例传递给另外一个实例,就需要额外地进行构造、赋值、销毁的操作。
    对于一些比较复杂的变量,的确是非常耗时并且消耗大的操作。(浪费指令时间、浪费内存)

    对于这样的函数返回:
    vector<string> str_split(const string& s) {
    vector<string> v;
    // ...
    return v; // v是左值,但优先移动,不支持移动时仍可复制。
    }

    标准要求先调用移动构造函数,如果不符合那么再调用拷贝构造函数。所以可以轻松地写出这种写法而不必担心效率问题。
    同时,现代编译器都会对返回值进行优化,成为RVO以及NRVO。所以不用太担心会多调用构造析构函数。

    对于完美转发,C++对于引用的转发有规则。传统的C++是无法对引用进行再引用的。但是现代的C++放宽了它的使用范围。
    只有右引用右值的时候,才会产生右引用。这也称为引用折叠。

    3、auto关键字的作用是什么?
    auto关键字为的是能够让编译器自动推导类型。自C++98之后,编译器对类型的推导变得越来越智能了。
    而我们在编写复杂代码的时候,冗长的类型不仅容易出错,有时也不容易人工推导出类型。
    因此auto可以简化我们的任务量,让类型的推导交给编译器完成。
    除了auto外,我们还可以使用decltype()来让编译器推导类型。

    read more

关注我们

微博
QQ群