Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. Italian
  4. Form Qml e classe in c++
Forum Updated to NodeBB v4.3 + New Features

Form Qml e classe in c++

Scheduled Pinned Locked Moved Solved Italian
21 Posts 3 Posters 6.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    VRonin
    wrote on 2 Jan 2018, 15:04 last edited by VRonin 1 Feb 2018, 15:08
    #8

    ti manca solo da aggiungere Q_INVOKABLE davanti a quei metodi.

    Occhio che subclassare un modello e' un campo minato. Se puoi, dichiara Players come Q_GADGET, e usa QStandardItemModel direttamente:

    class Player{
    Q_GADGET
    Q_PROPERTY(QString nick MEMBER m_nick)
    Q_PROPERTY(QString name MEMBER m_name)
    Q_PROPERTY(QString surname MEMBER m_surname)
    public:
    Player(const QString& nick,const QString& name ,const QString& surname)
    :m_nick(nick),m_name(name),m_surname(surname){}
    Player() = default;
    Player(const Player& other)=default;
    Player& operator=(const Player& other)=default;
    QString m_nick;
    QString m_name;
    QString m_surname;
    };
    
    class Game : public QObject{
    Q_OBJECT
    Q_PROPERTY(QAbstractItemModel* model READ model)
    Q_PROPERTY(ModeGame modeGame READ modeGame WRITE setModeGame NOTIFY modeGameChanged)
    Q_DISABLE_COPY(Game)
    public:
     enum ModeGame  { U_Mode = 0,  D_Mode,  T_Mode  };
    Q_ENUM(ModeGame)
    Game(QObject* parent = nullptr) :QObject(parent){
    m_model=new QStandardItemModel(this);
    m_model->inserColumn(0);
    }
    Q_SLOT void addPlayer(const QString& nick,const QString& name ,const QString& surname){
    const int newRow = m_model->rowCount();
    m_model->insertRow(newRow);
    m_model->setData(m_model->index(newRow,0),Player(nick,name,surname));
    }
    Q_SLOT void removePlayer(int index){
    m_model->removeRow(index);
    }
    QAbstractItemModel* model() const {return m_model}
    Q_SIGNAL void modeGameChanged(ModeGame modegame);
    void setModeGame(ModeGame modegame){
    if(m_modegame==modegame) return;
    m_modegame=modegame;
    modeGameChanged(modegame);
    }
    ModeGame modeGame() const{return m_modegame;}
    private:
    QAbstractItemModel* m_model;
    ModeGame m_modegame;
    };
    

    P.S. Q_ENUMS e' deprecato, usa Q_ENUM: https://woboq.com/blog/q_enum.html

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    1 Reply Last reply
    0
    • G Offline
      G Offline
      GiGa91
      wrote on 2 Jan 2018, 15:50 last edited by
      #9

      Perfetto ho capito che la mia soluzione è meglio che la metta di lato e uso la tua. Della tua soluzione però non mi sono chiare due cose e approfitto della tua pazienza per togliermi questi dubbi.

      La prima è: perche mi conviene usare dichiarare Players come Q_GADGET?

      La seconda: ho un errore con il setData ( m_model->setData(m_model->index(newRow,0),Player(nick,name,surname));)
      Ll'ho usato nel tuo stesso modo ma mi sfugge l'errore

      V 1 Reply Last reply 2 Jan 2018, 16:18
      0
      • G GiGa91
        2 Jan 2018, 15:50

        Perfetto ho capito che la mia soluzione è meglio che la metta di lato e uso la tua. Della tua soluzione però non mi sono chiare due cose e approfitto della tua pazienza per togliermi questi dubbi.

        La prima è: perche mi conviene usare dichiarare Players come Q_GADGET?

        La seconda: ho un errore con il setData ( m_model->setData(m_model->index(newRow,0),Player(nick,name,surname));)
        Ll'ho usato nel tuo stesso modo ma mi sfugge l'errore

        V Offline
        V Offline
        VRonin
        wrote on 2 Jan 2018, 16:18 last edited by
        #10

        @GiGa91 said in Form Qml e classe in c++:

        perche mi conviene usare dichiarare Players come Q_GADGET?

        E' semplicemente per incapsulare Player. se non lo dichiari come Q_GADGET dovresti, dentro Game, dichiarare cose tipo Q_INVOKABLE QString getNick(int row); mentre se e' Q_GADGET puoi usare direttamente le sue proprieta' nel delegate

        ho un errore con il setData

        Cosa ti scrive l'errore?

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        1 Reply Last reply
        0
        • G Offline
          G Offline
          GiGa91
          wrote on 2 Jan 2018, 16:36 last edited by
          #11

          Ah giusto non ci avevo pensato.

          Per quanto riguarda l'errore, me lo da a causa del fatto che gli sto dando "players". Precisamente questo:

          error: no matching function for call to ‘QAbstractItemModel::setData(QModelIndex, Player)’
          m_model->setData(m_model->index(newRow,0),Player(nick,name,surname));
          no known conversion for argument 2 from ‘Player’ to ‘const QVariant&’
          ^

          1 Reply Last reply
          0
          • V Offline
            V Offline
            VRonin
            wrote on 2 Jan 2018, 16:38 last edited by
            #12

            Giusto, sto dormendo.
            m_model->setData(m_model->index(newRow,0),QVariant::fromValue(Player(nick,name,surname)));

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            1 Reply Last reply
            0
            • G Offline
              G Offline
              GiGa91
              wrote on 3 Jan 2018, 09:29 last edited by
              #13

              Quasi tutto chiaro.. mi manca un passaggio solo.

              Avendo esportato la classe verso qml:

              Game game;
              engine.rootContext()->setContextProperty("Game", &game);
              

              ho a disposizione i metodi addPlayer e removePlayer che posso usare in modo molto semplice:

              onClicked: Game.addPlayer(qsTr(text_input_name.text), qsTr(text_input_surname.text), qsTr(text_input_nick.text))
              

              tramite la property io dovrei poter leggere il modello su Qml

              Q_PROPERTY(QAbstractItemModel* model READ model)
              

              Pero non riesco. Ad esempio:

              Button {
                          text: "Add"
                          onClicked: {
                              Game.addPlayer(qsTr(text_input_name.text), qsTr(text_input_surname.text), qsTr(text_input_nick.text))
                          }
                      }
              
                      Button {
                          text: "Rem"
                          onClicked: Game.removePlayer(index)
                      }
              
              
              
                      ListView {
                          id: listView
                          Layout.fillWidth: true
                          model: Game.model
                          delegate: listDelegate
                      }
                      Component {
                          id: listDelegate
                          Text {
                              id: name_text
                              text: Game.model.data(0,1)
                          }
                      }
              
              1 Reply Last reply
              0
              • V Offline
                V Offline
                VRonin
                wrote on 3 Jan 2018, 09:44 last edited by
                #14
                • qsTr non funziona cosi'. Puo' solo tradurre costanti e, comunque, non vedo il punto di tradurre un nome proprio
                • Il problema e' nel delegate text: Game.model.data(0,1) non funziona cosi'. E' un po' che non uso QML ma se ricordo bene era role.property quindi nel tuo caso qualcosa tipo text: display.nick + " - " + display.name + " " + display.surname

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  GiGa91
                  wrote on 3 Jan 2018, 09:59 last edited by
                  #15

                  ops ho sbagliato a ricopiare. Questo non centra nulla:

                  text: Game.model.data(0,1)
                  

                  Il punto che non capisco è proprio questo. Per esempio ti riporto un codice di esempio di Qml:

                  ListModel {
                      id: nameModel
                      ListElement { name: "Alice"; team: "Crypto" }
                      ListElement { name: "Bob"; team: "Crypto" }
                      ListElement { name: "Jane"; team: "QA" }
                      ListElement { name: "Victor"; team: "QA" }
                      ListElement { name: "Wendy"; team: "Graphics" }
                  }
                  Component {
                      id: nameDelegate
                      Text {
                          text: name;
                          font.pixelSize: 24
                          anchors.left: parent.left
                          anchors.leftMargin: 2
                      }
                  }
                  

                  Nel delegate dovrebbe bastare mettere "name" e in modo trasparente dovrebbe vedermi la propieta di ListElement (nel caso dell'esempio)
                  Usando la Q_PROPERTY sbaglio a pensare di ottenere la stessa cosa verso il modello Game?

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    VRonin
                    wrote on 3 Jan 2018, 10:46 last edited by VRonin 1 Mar 2018, 11:01
                    #16

                    esatto, name in quel caso e' il role in cui salvi "Alice".
                    Quando chiami m_model->setData in realta' i parametri sono 3: indice della cella da cambiare, valore da inserire e role del valore. Siccome noi non mettiamo nulla nel terzo parametro il default e' Qt::EditRole
                    In QML non usi Qt::EditRole ma il nome corrispondente (qui trovi la lista dei nomi per i role standard).
                    Io uso display invece di edit perche' in QStandardItemModel display e edit sono la stessa cosa (ma questo e' un dettaglio irrilevante)
                    Ora display ritorna una QVariant che contiene un Player. Puoi usare . per accedere alle sue proprieta' quindi display.nick (o edit.nick se preferisci)

                    quindi:

                    Component {
                        id: nameDelegate
                        Text {
                            text: edit.nick
                            font.pixelSize: 24
                            anchors.left: parent.left
                            anchors.leftMargin: 2
                        }
                    }
                    

                    dovrebbe funzionare

                    Edit:
                    set ti piace di piu' puoi anche modificare il costruttore di Game cosi':

                    Game(QObject* parent = nullptr) :QObject(parent){
                    m_model=new QStandardItemModel(this);
                    m_model->inserColumn(0);
                    QHash<int, QByteArray> roleNames = m_model->roleNames();
                    roleNames.insert(Qt::UserRole,"player");
                    static_cast<QStandardItemModel*>(m_model)->setItemRoleNames(roleNames);
                    }
                    

                    e quando chiami setData aggiungi il terzo parametro: m_model->setData(m_model->index(newRow,0),QVariant::fromValue(Player(nick,name,surname)),Qt::UserRole);

                    adesso in QML puoi fare:

                    Component {
                        id: nameDelegate
                        Text {
                            text: player.nick
                            font.pixelSize: 24
                            anchors.left: parent.left
                            anchors.leftMargin: 2
                        }
                    }
                    

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      GiGa91
                      wrote on 3 Jan 2018, 11:00 last edited by
                      #17

                      Ti riporto l'errore che sicuramente spiega meglio cio che vorrei dirti:

                      ReferenceError: edit is not defined
                      

                      Lo stesso valeva per display

                      1 Reply Last reply
                      0
                      • V Offline
                        V Offline
                        VRonin
                        wrote on 3 Jan 2018, 11:25 last edited by VRonin 1 Mar 2018, 11:28
                        #18

                        Strano perche' ha funzionato per me. Avevo praticamente la stessa tua domanda: https://forum.qt.io/topic/71433/best-practice-to-add-dynamic-qml-from-c-data/12

                        Probabilmente devi solo aggiungere Q_DECLARE_METATYPE(Player) in player.h e qmlRegisterType<Player>("com.game", 1, 0, "Player"); nella main()

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        1 Reply Last reply
                        0
                        • G Offline
                          G Offline
                          GiGa91
                          wrote on 3 Jan 2018, 12:45 last edited by GiGa91 1 Mar 2018, 13:08
                          #19

                          Perdona la mia ignoranza, ma io posso esportare la classe player tramite qmlRegistrerType? Non è definita come public Qobject e se devo essere sincero ci avevo gia provato ma ottenevo/ottengo questo errore:

                           error: cannot convert ‘QQmlPrivate::QQmlElement<Player>*’ to ‘QObject*’ for argument ‘1’ to ‘void QQmlPrivate::qdeclarativeelement_destructor(QObject*)’
                                       QQmlPrivate::qdeclarativeelement_destructor(this);
                                                                                  ^
                          

                          Ho aggiunto Q_DECLARE_METATYPE(Player) in players.h

                          Considerando che a te il codice funzione e la probabilità che io abbia dimenticato qualcosa è alta riporto i miei quattro file:

                          main.cpp

                          #include <QGuiApplication>
                          #include <QQmlApplicationEngine>
                          #include <QQmlContext>
                          #include <QtQml>
                          
                          #include "Classe_Game/Game.h"
                          #include "Classe_Players/Players.h"
                          
                          int main(int argc, char *argv[])
                          {
                              QGuiApplication app(argc, argv);
                              //qmlRegisterType<Player>("com.helloworld.qmlcomponents",1,0,"Player");
                          
                              QQmlApplicationEngine engine;
                          
                          
                              Game game;
                              engine.rootContext()->setContextProperty("Game", &game);
                          
                              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                              if (engine.rootObjects().isEmpty())
                                  return -1;
                          
                          
                              return app.exec();
                          }
                          
                          

                          Players.h

                          #ifndef PLAYERS_H
                          #define PLAYERS_H
                          #include <QObject>
                          
                          class Player
                          {
                              Q_GADGET
                          
                              Q_PROPERTY(QString nick MEMBER m_nick)
                              Q_PROPERTY(QString name MEMBER m_name)
                              Q_PROPERTY(QString surname MEMBER m_surname)
                          public:
                              Player(const QString& nick,const QString& name ,const QString& surname)
                                  :m_nick(nick),m_name(name),m_surname(surname){}
                              Player() = default;
                              Player(const Player& other)=default;
                              Player& operator=(const Player& other)=default;
                              QString m_nick;
                              QString m_name;
                              QString m_surname;
                          };
                          Q_DECLARE_METATYPE(Player)
                          #endif // PLAYERS_H
                          

                          Game.h

                          #ifndef GAME_H
                          #define GAME_H
                          #include <QStandardItemModel>
                          #include <QList>
                          
                          #include "Classe_Players/Players.h"
                          
                          class Game : public QObject{
                              Q_OBJECT
                              Q_PROPERTY(QAbstractItemModel* model READ model)
                              Q_PROPERTY(ModeGame modeGame READ modeGame WRITE setModeGame NOTIFY modeGameChanged)
                              Q_DISABLE_COPY(Game)
                          public:
                              enum ModeGame{NS, Static, Projector};
                              Q_ENUM(ModeGame)
                          
                              Game(QObject* parent = nullptr) :QObject(parent){
                              m_model=new QStandardItemModel(this);
                              m_model->insertColumn(0);
                              QHash<int, QByteArray> roleNames = m_model->roleNames();
                              roleNames.insert(Qt::UserRole,"player");
                              static_cast<QStandardItemModel*>(m_model)->setItemRoleNames(roleNames);
                              }
                          
                              Q_SLOT void addPlayer(const QString& nick,const QString& name ,const QString& surname){
                                  const int newRow = m_model->rowCount();
                                  m_model->insertRow(newRow);
                                  m_model->setData(m_model->index(newRow,0),QVariant::fromValue(Player(nick,name,surname)),Qt::UserRole);
                              }
                          
                              Q_SLOT void removePlayer(int index){
                                  m_model->removeRow(index);
                              }
                          
                              QAbstractItemModel* model() const {
                                  return m_model;
                              }
                          
                              Q_SIGNAL void modeGameChanged(ModeGame modegame);
                          
                              void setModeGame(ModeGame modegame){
                                  if(m_modegame==modegame) return;
                                  m_modegame=modegame;
                                  modeGameChanged(modegame);
                              }
                              ModeGame modeGame() const{return m_modegame;}
                          private:
                              QAbstractItemModel* m_model;
                              ModeGame m_modegame;
                          };
                          #endif // GAME_H
                          
                          

                          main.qml

                          import QtQuick 2.10
                          import QtQuick.Window 2.10
                          import QtQuick.Layouts 1.3
                          import QtQuick.Controls 1.4
                          
                          Window {
                              visible: true
                              width: 640
                              height: 480
                              title: qsTr("Hello World")
                          
                          
                              ColumnLayout {
                                  id: rowLayout
                                  objectName: "rowLayout"
                                  anchors.fill: parent
                          
                                  TextInput {
                                      id: text_input_name
                                      color: "red"
                                      text: "name"
                                      Layout.fillWidth: true
                                      focus: true
                                  }
                          
                                  TextInput {
                                      id: text_input_surname
                                      color: "red"
                                      text: "surname"
                                      Layout.fillWidth: true
                                      focus: true
                                  }
                          
                                  TextInput {
                                      id: text_input_nick
                                      color: "red"
                                      text: "nick"
                                      Layout.fillWidth: true
                                      focus: true
                                  }
                          
                          
                                  Button {
                                      text: "Add"
                                      onClicked: {
                                          Game.addPlayer(text_input_name.text, text_input_surname.text, text_input_nick.text)
                                      }
                                  }
                          
                                  Button {
                                      text: "Rem"
                                      //onClicked: Game.removePlayer(index)
                                  }
                          
                          
                          
                                  ListView {
                                      width: 200; height: 250
                          
                                      model: Game
                                      delegate: Text {
                                          text: players.name
                                      }
                                  }
                              }
                          }
                          
                          
                          1 Reply Last reply
                          0
                          • V Offline
                            V Offline
                            VRonin
                            wrote on 3 Jan 2018, 13:48 last edited by VRonin 1 Mar 2018, 13:53
                            #20

                            @GiGa91 said in Form Qml e classe in c++:

                            model: Game

                            il modello non e' Game, e' Game.model

                            text: players.name

                            il role non e' players, e' player

                            Game.addPlayer(text_input_name.text, text_input_surname.text, text_input_nick.text)

                            Hai sbagliato l'ordine degli argomenti: Game.addPlayer(text_input_nick.text, text_input_name.text, text_input_surname.text)

                            Q_DECLARE_METATYPE(Player)

                            Non e' necessario, Q_GADGET fa gia' tutto

                            //onClicked: Game.removePlayer(index)

                            devi dare un id a ListView (per esepio id: playerView) e poi fare onClicked: Game.removePlayer(playerView.currentIndex)

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              GiGa91
                              wrote on 3 Jan 2018, 14:45 last edited by
                              #21

                              Era superscontato che commettevo errori. Adesso funziona perfettamente.
                              Infinitamente grazie per la pazienza che hai avuto

                              1 Reply Last reply
                              0

                              17/21

                              3 Jan 2018, 11:00

                              • Login

                              • Login or register to search.
                              17 out of 21
                              • First post
                                17/21
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved