IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Quick Discussion :

Signal C++ transmis à un composant QML


Sujet :

Qt Quick

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 50
    Points : 28
    Points
    28
    Par défaut Signal C++ transmis à un composant QML
    Bonjour,

    J’émets un signal depuis une classe, et que je transmet à un composant QML via la fonction (c++) et via mon composant QML.

    Cette classe est créée sur l'event d'un bouton. (je vois bien les actions liées a cette classe).
    Par contre, pour récupérer le signal émis par la classe , c'est la que ça coince.
    QML ne voit pas le signal.
    En debug, je vois passer des warnings :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     QML Connections: Binding loop detected for property "target"
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Expression qrc:/Signin.qml:8:17 depends on non-NOTIFYable properties:
    Je vous met le code ci-dessous des classes concernées.

    Signin.qml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    import QtQuick 2.10
    import QtQuick.Controls 2.3
     
    Item {
        id: test
     
        Connections{
            target: http
            onLogin: console.log("test")
        }
     
        TextInput {
            id: login
            x: 280
            y: 183
            width: 100
            height: 23
            text: qsTr("Login ")
            font.pixelSize: 12
        }
     
        TextInput {
            id: password
            x: 280
            y: 219
            width: 100
            height: 20
            text: qsTr("Password")
            echoMode: TextInput.Password
            font.pixelSize: 12
        }
     
        Button {
            id: send
            x: 280
            y: 257
            width: 61
            height: 25
            text: qsTr("Connect")
            onClicked:{
                http.start_request("myurl", "443", "/login", 11, "POST", "username=" + login.text + "&password=" + password.text)
            }
        }
    }
    Main.qml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    import QtQuick 2.7
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.3
    import QtQuick.Layouts 1.3
     
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Doze Chat ")
     
        Index {
            id: chat
            visible: false
        }
     
        SwipeView {
            id: swipeView
            anchors.fill: parent
            currentIndex: tabBar.currentIndex
     
            Signin {
                id: signin
            }
     
            Signup {
                id: signup
            }
    }
     
        TabBar {
                id: tabBar
                x: 274
                y: 123
                currentIndex: swipeView.currentIndex
     
                TabButton {
                    text: qsTr("Login")
                }
                TabButton {
                    text: qsTr("Register")
                }
        }
     
    }
    request.h
    Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    #ifndef REQUEST_H
    #define REQUEST_H
     
    #include <QString>
    #include "hash_password.h"
    #include <boost/beast/core.hpp>
    #include <boost/beast/http.hpp>
    #include <boost/beast/version.hpp>
    #include <boost/asio/connect.hpp>
    #include <boost/asio/ip/tcp.hpp>
    #include <boost/asio/ssl/error.hpp>
    #include <boost/asio/ssl/stream.hpp>
    #include <QObject>
     
    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/json_parser.hpp>
     
    using tcp = boost::asio::ip::tcp;
    namespace ssl = boost::asio::ssl;
    namespace http = boost::beast::http;
    namespace pt = boost::property_tree;
     
    class request : public QObject, public std::enable_shared_from_this<request>
    {
        Q_OBJECT
     
    signals:
        void login();
     
    public:
        explicit request(boost::asio::io_context& ioc, boost::asio::ssl::context& ctx);
        void run(char const* host, char const* port, char const* target, int version, QString method, QString body = NULL);
        Q_INVOKABLE void start_request( QString host, QString port, QString target, int version, QString method, QString body = NULL);
        std::string respond;
        QString GetmessageError;
     
    private:
        hash_password hashed_password;
        tcp::resolver resolver;
        boost::asio::ssl::stream<tcp::socket> stream;
        boost::beast::flat_buffer buffer;
        boost::beast::http::request<http::string_body> req;
        boost::beast::http::response<http::string_body> res;
     
        void on_resolve(boost::system::error_code ec, boost::asio::ip::tcp::resolver::results_type results);
        void on_connect(boost::system::error_code ec);
        void on_handshake(boost::system::error_code ec);
        void on_write(boost::system::error_code ec, std::size_t bytes_transferred);
        void on_read(boost::system::error_code ec, std::size_t bytes_transferred);
        void on_shutdown(boost::system::error_code ec);
        void fail(boost::system::error_code ec, char const* what);
     
        //json_parser Jsonresponse;
        std::string GetApiResponse(std::stringstream Jsonres, pt::ptree root);
     
    };
     
    #endif // REQUEST_H

    request.cpp
    Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    #include "request.h"
    #include <iostream>
    #include <boost/beast/http/verb.hpp>
    #include <boost/utility/string_view.hpp>
     
    //#include <boost/property_tree/ptree.hpp>
    //#include <boost/property_tree/json_parser.hpp>
     
    request::request(boost::asio::io_context& ioc, ssl::context& ctx) : resolver(ioc) , stream(ioc, ctx)
    {
     
    }
     
    void request::fail(boost::system::error_code ec, char const* what)
    {
        std::cerr << what << ": " << ec.message() << "\n";
    }
     
    void request::run(char const* host, char const* port, char const* target, int version, QString method, QString body)
    {
        // Set SNI Hostname (many hosts need this to handshake successfully)
        if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
        {
            boost::system::error_code ec{static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category()};
            std::cerr << ec.message() << "\n";
            respond = "test" ;
            return;
        }
     
        // Set up an HTTP GET request message
        http::verb method_verb;
        boost::string_view method_strview ;
        method_strview = method.toStdString();
        method_verb = boost::beast::http::string_to_verb(method_strview);
        req.version(version);
        req.method(method_verb);
        req.target(target);
        req.set(http::field::host, host);
        req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
        req.set(http::field::content_type, "application/x-www-form-urlencoded");
        req.body() = body.toStdString() ;
        req.prepare_payload();
     
        // Look up the domain name
        resolver.async_resolve(host, port, std::bind(&request::on_resolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
     }
     
    void request::on_resolve(boost::system::error_code ec, tcp::resolver::results_type results)
    {
        if(ec){
            //return fail(ec, "resolve");
            respond = "test" ;
        }
        // Make the connection on the IP address we get from a lookup
        boost::asio::async_connect(stream.next_layer(), results.begin(), results.end(), std::bind( &request::on_connect, shared_from_this(), std::placeholders::_1));
    }
     
    void request::on_connect(boost::system::error_code ec)
    {
        if(ec){
            //return fail(ec, "connect");
             respond = ec.message();
            }
     
        // Perform the SSL handshake
        stream.async_handshake(ssl::stream_base::client, std::bind(&request::on_handshake, shared_from_this(), std::placeholders::_1));
    }
     
    void request::on_handshake(boost::system::error_code ec)
    {
        if(ec){
            return fail(ec, "handshake");
        }
     
        // Send the HTTP request to the remote host
        http::async_write(stream, req, std::bind(&request::on_write, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
    }
     
    void request::on_write(boost::system::error_code ec, std::size_t bytes_transferred)
    {
        boost::ignore_unused(bytes_transferred);
     
        if(ec)
            return fail(ec, "write");
     
        // Receive the HTTP response
        http::async_read(stream, buffer, res, std::bind(&request::on_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
    }
     
    void request::on_read(boost::system::error_code ec, std::size_t bytes_transferred)
    {
        boost::ignore_unused(bytes_transferred);
     
        if(ec)
            return fail(ec, "read");
     
        switch(res.result_int())
        {
        case 200: {
            emit login(); //Le signal est la !
            std::cout<<res.result_int()<<std::endl;
                  }
            break;
     
        }
     
        // Gracefully close the stream
        stream.async_shutdown(std::bind(&request::on_shutdown, shared_from_this(), std::placeholders::_1));
    }
     
    void request::on_shutdown(boost::system::error_code ec)
    {
        if(ec == boost::asio::error::eof)
        {
            ec.assign(0, ec.category());
        }
        if(ec)
          return fail(ec, "shutdown");
     
        // If we get here then the connection is closed gracefully
    }
     
    void request::start_request(QString host, QString port, QString target, int version, QString method, QString body)
    {
        boost::asio::io_context ioc;
        ssl::context ctx{ssl::context::sslv23_client};
     
        const char* std_host = host.toStdString().c_str();
        const char* std_port = port.toStdString().c_str();
        const char* std_target = target.toStdString().c_str();
        const char* std_method = method.toStdString().c_str();
        const char* std_body = body.toStdString().c_str();
     
        std::make_shared<request>(ioc, ctx)->run(std_host, std_port, std_target, version, std_method, std_body );
        ioc.run();
    }
     
    std::string request::GetApiResponse(std::stringstream Jsonres, pt::ptree root)
    {
        pt::read_json(Jsonres, root);
        std::cout<<root.get<std::string>("user.permission")<<std::endl;
        return root.get<std::string>("user.permission");
    }

    main.cpp
    Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
     
    #include <iostream>
    #include <boost/asio.hpp>
    #include <boost/thread.hpp>
     
    #include "tcp_client.h"
    #include "message.h"
    #include "observer.h"
    #include "request.h"
     
    #include <QDebug>
    #include <QObject>
    #include <QQuickItem>
    #include <QQmlContext>
     
    struct testmessage : public observer
    {
        virtual void update(message data)
        {
            switch (data.m_type)
            {
            case  message::NEW_MSG:
            {
                std::string chaine = "[" + data.m_login + "]: ";
                chaine += data.m_message;
                std::cout <<"test"<< chaine << std::endl;
            }
                break;
            case message::PERSON_CONNECTED:  std::cout << "Nouvelle personne!" << std::endl;
                break;
            case message::PERSON_LEAVED: std::cout << "Une personne nous quitte" << std::endl;
                break;
                //default:
            }
        }
    };
     
    boost::asio::io_service io_service;
     
    int main(int argc, char *argv[])
    {
        //test connexion
     
        QGuiApplication app(argc, argv);
     
        QQmlApplicationEngine engine;
     
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("192.168.226.132"), 4000);
        std::string login = "allo";
     
        boost::asio::io_context ioc;
        boost::asio::ssl::context ctx{ssl::context::sslv23_client};
        tcp_client c(io_service, endpoint, login);
        request request(ioc, ctx);
     
     
        engine.rootContext()->setContextProperty("tcp_client", &c);
        engine.rootContext()->setContextProperty("http", &request);
     
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
     
        return app.exec();
    }

    En sachant que j'ai crée une simple application QML, avec un bouton qui appelle une classe c++. cette classe émet un signal. Ce signal est bien reçu par QML.
    La je comprends plus rien.
    PS : Je vois bien le std::cout du switch concerné qui m'affiche "200"

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 50
    Points : 28
    Points
    28
    Par défaut
    J'ai passé la méthode qui émet le signal en Public :
    Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public:
        explicit request(boost::asio::io_context& ioc, boost::asio::ssl::context& ctx);
        void run(char const* host, char const* port, char const* target, int version, QString method, QString body = NULL);
        Q_INVOKABLE void start_request( QString host, QString port, QString target, int version, QString method, QString body = NULL);
        std::string respond;
        QString GetmessageError;
        void on_read(boost::system::error_code ec, std::size_t bytes_transferred);

    le signal n'est toujours pas vu coté QML

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 50
    Points : 28
    Points
    28
    Par défaut
    En fait, le signal doit être émis dans la même méthode appelé en QML.

    Dans mon cas, je doit émettre le signal dans la méthode start_request() et non onread()

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débuter] [PathView] Insérer des composant QML
    Par caymus dans le forum Qt Quick
    Réponses: 0
    Dernier message: 06/02/2013, 11h11
  2. Réponses: 2
    Dernier message: 16/11/2012, 21h19
  3. Le composant QML ShaderEffectItem et QGraphicsView
    Par Michel Rotta dans le forum Qt Quick
    Réponses: 0
    Dernier message: 26/05/2011, 21h22
  4. Installer ses composants
    Par Geronimo dans le forum C++Builder
    Réponses: 14
    Dernier message: 18/06/2002, 14h51
  5. Re-dimensionnement automatique de composants
    Par ludo_7 dans le forum C++Builder
    Réponses: 10
    Dernier message: 16/05/2002, 16h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo