Comunicação entre Qt e QML



  • Olá a todos,

     Conheço Qt já a algum tempo, e tenho me envolvido mais e mais com ele nos últimos meses. Mas como não uso somente ele como framework principal, ainda não me aprofundei ao nível que gostaria. 
     Como todas as linguagens / frameworks, considero o Qt excelente, fantástico em alguns aspectos, e um verdadeiro porre em outros... Como exemplo, cito as constantes necessidades de usar subclasses em diversas situações, que ao meu  ver, poderiam ser incorporadas de maneira mais tranquila ao próprio framework.
    
     Tenho percebido que o QML está ganhando cada vez mais atenção, e recebendo atualizações em um ritmo bastante acelerado em relação ao Qt / QWidgets... E gostaria de começar a usar para aplicativos desktop. O que me impede de fazer isso atualmente, é que preciso de forte suporte  a acesso e manipulação de bancos de dados, tanto MySql como SQlite... e neste aspecto, Qt/c++ é excelente. Sei que existe a possibilidade de criar os models e até as funções de backend totalmente em Qt e deixar para o QML apenas a camada de apresentação.
    

    Isso posto, minha pergunta, ou melhor, meu pedido é: Alguém poderia explicar, como se fosse para uma criança de 10 anos( ou 8...), como faço para realizar esta comunicação ? Poderia ser com um exemplo de model com relacionamento bem simples, estilo Estados e Cidades ?

    Desde já, agradeço.



  • Olá Pessoal... Será que forcei muito ? Pode ser então como se fosse para um adolescente, de 15 ou 16 anos... Melhora ? :)



  • AdelarDuarte,

    Usar as classes em C++ no QML é super tranquilo.

    Para o QML "enxergar" os membros de sua classe C++, você usa a macro Q_PROPERTY (que está descrito "aqui":http://qt-project.org/doc/qt-5/qtqml-cppintegration-exposecppattributes.html), mais ou menos assim:

    @class Message : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
    public:
    void setAuthor(const QString &a) {
    if (a != m_author) {
    m_author = a;
    emit authorChanged();
    }
    }
    QString author() const {
    return m_author;
    }
    signals:
    void authorChanged();
    private:
    QString m_author;
    };
    @

    Com isso feito, você precisa "registrar" sua classe na engine do QML.

    @
    int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

     QQmlEngine engine;
     Message msg;    //Seu objeto
     engine.rootContext()->setContextProperty("msg", &msg); 
     QQmlComponent component(&engine, QUrl::fromLocalFile("MyItem.qml"));
     component.create();
    
     return app.exec();
    

    }
    @

    Aí é só usar a propriedade no QML:
    @
    // MyItem.qml
    import QtQuick 2.0

    Text {
    width: 100; height: 100
    text: msg.author // invokes Message::author() to get this value

    Component.onCompleted: {
        msg.author = "Jonah"  // invokes Message::setAuthor()
    }
    

    }
    @

    Este é um exemplo bem simples.

    Para export um método, você pode usar a macro Q_INVOKABLE, ou declarar um public slot:

    @
    class MessageBoard : public QObject
    {
    Q_OBJECT
    public:
    Q_INVOKABLE bool postMessage(const QString &msg) {
    qDebug() << "Called the C++ method with" << msg;
    return true;
    }

    public slots:
    void refresh() {
    qDebug() << "Called the C++ slot";
    }
    };
    @

    Definir um model para o QML segue a mesma "linha":http://qt-project.org/doc/qt-5/qtquick-modelviewsdata-cppmodels.html.



  • Se ficou confuso é só dizer.



  • TioRoy, valeu pela resposta. Já deu uma clareada no funcionamento... Só para confirmar, então, seguindo este princípio, posso passar models também, não importando se eles são baseados em QSqltableModels ou mesmo QSqlRelationalTableModels... É isso ?

    Desde já, agradeço seu tempo.



  • É isso sim. Um bq. QStringList, por exemplo serve como model para p QML.

    Outro exemplo: Se pegar a classe Message lá do meu primeiro post (que tem uma propriedade author), e fazer uma lista assim:

    @
    QList<QObject*> mymodel;
    mymodel.append(new Message("Author1"));
    mymodel.append(new Message("Author2"));
    mymodel.append(new Message("Author3"));

    QQmlContext *ctxt = view.rootContext();
    ctxt->setContextProperty("myModel", QVariant::fromValue(mymodel));
    

    @

    Aí no QML você poderia acessar a sua lista:

    @
    ListView {
    width: 100; height: 100

    model: myModel
    delegate: Rectangle {
        height: 25
        width: 100
        Text { text: model.modelData.author }
    }
    

    }
    @



  • Obrigado pelo retorno. Os esclarecimentos foram muito bons.

    Té +


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.