Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. German
  4. QMap im globalen Bereich
Forum Updated to NodeBB v4.3 + New Features

QMap im globalen Bereich

Scheduled Pinned Locked Moved Solved German
13 Posts 3 Posters 2.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.
  • T Offline
    T Offline
    Throndar
    wrote on last edited by Throndar
    #1

    Hallo,

    ich versuche gerade mein Projekt umzustrukturieren. Ich generiere aktuell mehrere Clients die jeweils ein Object einer "Client-Klasse" sind. Diese ganzen Clients sind in einer QMap abgelegt mit Ihrer IP als Schlüssel.

    Da ich das ganze Programmübergreifend benutzen muss hatte ich mir überlegt das es sinnvoll wäre in der Main direkt die QMap zu erstellen was ich per:

    QMap<QString, MovieClient*> movieClients;
    

    erstellt habe. Nun hänge ich aber beim Versuch die QMap im Context bekannt zu machen.

    Normale Objekte funktionieren ja nach dem Schema:

    UdpReceiver uReceiver;
    engine.rootContext()->setContextProperty("UdpReceiver", &uReceiver);
    

    was den Fehler "no matching member function for call to "setContextProperty" liefert, auch der Versuch mit "setContextObject" hat keinen Erfolg gebracht.

    Hat jemand einen Tipp für mich wie ich die QMap an der Stelle Programmweit erreichbar machen kann?
    Ich wollte die QMap mit den Werten die z.B. die uReceiver erhält füllen und im QML auf den Inhalt dann zugreifen. Aktuell habe ich die QMap im Receiver direkt liegen so das sie gefüllt wird mit den Daten die der Receiver erhält. Da ich aber noch Werte später im Programm nachtragen wollte dachte ich mir wäre eine zentrale Stelle wo alle darauf zugreifen können zum ablegen der QMap sinnvoller oder?

    K 1 Reply Last reply
    0
    • T Throndar

      Hallo,

      ich versuche gerade mein Projekt umzustrukturieren. Ich generiere aktuell mehrere Clients die jeweils ein Object einer "Client-Klasse" sind. Diese ganzen Clients sind in einer QMap abgelegt mit Ihrer IP als Schlüssel.

      Da ich das ganze Programmübergreifend benutzen muss hatte ich mir überlegt das es sinnvoll wäre in der Main direkt die QMap zu erstellen was ich per:

      QMap<QString, MovieClient*> movieClients;
      

      erstellt habe. Nun hänge ich aber beim Versuch die QMap im Context bekannt zu machen.

      Normale Objekte funktionieren ja nach dem Schema:

      UdpReceiver uReceiver;
      engine.rootContext()->setContextProperty("UdpReceiver", &uReceiver);
      

      was den Fehler "no matching member function for call to "setContextProperty" liefert, auch der Versuch mit "setContextObject" hat keinen Erfolg gebracht.

      Hat jemand einen Tipp für mich wie ich die QMap an der Stelle Programmweit erreichbar machen kann?
      Ich wollte die QMap mit den Werten die z.B. die uReceiver erhält füllen und im QML auf den Inhalt dann zugreifen. Aktuell habe ich die QMap im Receiver direkt liegen so das sie gefüllt wird mit den Daten die der Receiver erhält. Da ich aber noch Werte später im Programm nachtragen wollte dachte ich mir wäre eine zentrale Stelle wo alle darauf zugreifen können zum ablegen der QMap sinnvoller oder?

      K Offline
      K Offline
      koahnig
      wrote on last edited by
      #2

      @Throndar

      Beim Ausdruck "Gloabaler Speicher" bekommen einige schon Schnappatmung. Vorteil ist natürlich, dass jeder direkt darauf zugreifen kann. Der Nachteil ist aber auch dass jeder direkt unkontrolliert darauf zugreifen. Dies ist nicht unbedingt reentrant und kann zu seltsamen Phänomenen führen.

      Ich würde die Liste zumindest nur als statisches Member in eine Klasse packen. Ueber statische Routinen kannst du dann auch von überall her zugreifen, aber du hast wenigstens eine Kontrolle wie zugegriffen wird.

      Vote the answer(s) that helped you to solve your issue(s)

      aha_1980A T 2 Replies Last reply
      2
      • K koahnig

        @Throndar

        Beim Ausdruck "Gloabaler Speicher" bekommen einige schon Schnappatmung. Vorteil ist natürlich, dass jeder direkt darauf zugreifen kann. Der Nachteil ist aber auch dass jeder direkt unkontrolliert darauf zugreifen. Dies ist nicht unbedingt reentrant und kann zu seltsamen Phänomenen führen.

        Ich würde die Liste zumindest nur als statisches Member in eine Klasse packen. Ueber statische Routinen kannst du dann auch von überall her zugreifen, aber du hast wenigstens eine Kontrolle wie zugegriffen wird.

        aha_1980A Offline
        aha_1980A Offline
        aha_1980
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Schnappatmung

        Der war gut :)

        Aber ehrlich, globale Variablen in C++ sind nicht ganz ungefährlich. Zum Beispiel wird int globalInt = 0 keine großen Problem verursachen, da er beim Programmstart initialisiert wird. Dagegen muss für QMap<QString, MovieClient*> movieClients; ein Klassenkonstruktur aufgerufen werden; wann das passiert ist in C++ undefiniert. Es kann also passieren, dass Du auf die Map zugreifst bevor sie initialisiert ist und das gibt einen schönen Crash :)

        Ehrlicherweise muss ich sagen, dass es auch für dieses Problem in Qt eine Lösung gibt, und zwar Q_GLOBAL_STATIC. Besser ist aber wie von @koahnig vorgeschlagen, statische Membervariablen zu verwenden.

        Grüße

        Qt has to stay free or it will die.

        T 1 Reply Last reply
        2
        • K koahnig

          @Throndar

          Beim Ausdruck "Gloabaler Speicher" bekommen einige schon Schnappatmung. Vorteil ist natürlich, dass jeder direkt darauf zugreifen kann. Der Nachteil ist aber auch dass jeder direkt unkontrolliert darauf zugreifen. Dies ist nicht unbedingt reentrant und kann zu seltsamen Phänomenen führen.

          Ich würde die Liste zumindest nur als statisches Member in eine Klasse packen. Ueber statische Routinen kannst du dann auch von überall her zugreifen, aber du hast wenigstens eine Kontrolle wie zugegriffen wird.

          T Offline
          T Offline
          Throndar
          wrote on last edited by Throndar
          #4

          Hallo @koahnig ,

          danke für deine Hilfe und static ist eigentlich genau das was Sinn ergibt für meine Clientliste.

          Ich habe gerade mal etwas gesucht, mit "static" bleibt ja eine Variable erhalten auch wenn die Funktion die sie erstellt beendet ist, nur waren die Beispiele dich ich im Netz gefunden haben bisher so aufgebaut das über eine static int zum Beispiel ein Zähler für die Anzahl der Aufrufe einer Funktion gebaut wurde.

          Meine erste Idee einfach bei der Erstellung der QMap ein "static" davor zu setzen um es als statisch zu kennzeichnen war nicht erfolgreich.

          static QMap<QString, MovieClient*> movieClients;
          
          lieferte:
          udpreceiver.obj:-1: Fehler: LNK2001: unresolved external symbol "public: static class QMap<class QString,class MovieClient *> UdpReceiver::movieClients" (?movieClients@UdpReceiver@@2V?$QMap@VQString@@PEAVMovieClient@@@@A)
          

          womit ich leider nichts anfangen konnte.

          Da du "statischen Routinen" erwähnt hast hatte ich gehofft das mir der Ansatz plus Google mir weiter hilft was leider nicht der Fall war. Kannst du mir vielleicht sagen was du mit den statischen Routinen meintest?

          K 1 Reply Last reply
          0
          • aha_1980A aha_1980

            Schnappatmung

            Der war gut :)

            Aber ehrlich, globale Variablen in C++ sind nicht ganz ungefährlich. Zum Beispiel wird int globalInt = 0 keine großen Problem verursachen, da er beim Programmstart initialisiert wird. Dagegen muss für QMap<QString, MovieClient*> movieClients; ein Klassenkonstruktur aufgerufen werden; wann das passiert ist in C++ undefiniert. Es kann also passieren, dass Du auf die Map zugreifst bevor sie initialisiert ist und das gibt einen schönen Crash :)

            Ehrlicherweise muss ich sagen, dass es auch für dieses Problem in Qt eine Lösung gibt, und zwar Q_GLOBAL_STATIC. Besser ist aber wie von @koahnig vorgeschlagen, statische Membervariablen zu verwenden.

            Grüße

            T Offline
            T Offline
            Throndar
            wrote on last edited by
            #5

            Hallo @aha_1980

            ich habe versucht mich in die Q_GLOBAL_STATIC und Q_GLOBAL_STATIC_WITH_ARGS einzulesen, und bin jetzt gerade etwas verwirrt. Nach dem was ich gelesen habe erzeugen die beiden ein Object des übergebenen Typs (mit bzw ohne Argumente).

            Für eine QMap wie ich sie verwenden wollte (da ich mehrere gleiche Objekte erstellen will) scheine ich die nicht nutzen zu können, oder habe ich das falsch verstanden?

            1 Reply Last reply
            0
            • T Throndar

              Hallo @koahnig ,

              danke für deine Hilfe und static ist eigentlich genau das was Sinn ergibt für meine Clientliste.

              Ich habe gerade mal etwas gesucht, mit "static" bleibt ja eine Variable erhalten auch wenn die Funktion die sie erstellt beendet ist, nur waren die Beispiele dich ich im Netz gefunden haben bisher so aufgebaut das über eine static int zum Beispiel ein Zähler für die Anzahl der Aufrufe einer Funktion gebaut wurde.

              Meine erste Idee einfach bei der Erstellung der QMap ein "static" davor zu setzen um es als statisch zu kennzeichnen war nicht erfolgreich.

              static QMap<QString, MovieClient*> movieClients;
              
              lieferte:
              udpreceiver.obj:-1: Fehler: LNK2001: unresolved external symbol "public: static class QMap<class QString,class MovieClient *> UdpReceiver::movieClients" (?movieClients@UdpReceiver@@2V?$QMap@VQString@@PEAVMovieClient@@@@A)
              

              womit ich leider nichts anfangen konnte.

              Da du "statischen Routinen" erwähnt hast hatte ich gehofft das mir der Ansatz plus Google mir weiter hilft was leider nicht der Fall war. Kannst du mir vielleicht sagen was du mit den statischen Routinen meintest?

              K Offline
              K Offline
              koahnig
              wrote on last edited by
              #6

              @Throndar said in QMap im globalen Bereich:

              Hallo @koahnig ,

              danke für deine Hilfe und static ist eigentlich genau das was Sinn ergibt für meine Clientliste.

              Ich habe gerade mal etwas gesucht, mit "static" bleibt ja eine Variable erhalten auch wenn die Funktion die sie erstellt beendet ist, nur waren die Beispiele dich ich im Netz gefunden haben bisher so aufgebaut das über eine static int zum Beispiel ein Zähler für die Anzahl der Aufrufe einer Funktion gebaut wurde.

              Meine erste Idee einfach bei der Erstellung der QMap ein "static" davor zu setzen um es als statisch zu kennzeichnen war nicht erfolgreich.

              static QMap<QString, MovieClient*> movieClients;
              
              lieferte:
              udpreceiver.obj:-1: Fehler: LNK2001: unresolved external symbol "public: static class QMap<class QString,class MovieClient *> UdpReceiver::movieClients" (?movieClients@UdpReceiver@@2V?$QMap@VQString@@PEAVMovieClient@@@@A)
              

              womit ich leider nichts anfangen konnte.

              Da du "statischen Routinen" erwähnt hast hatte ich gehofft das mir der Ansatz plus Google mir weiter hilft was leider nicht der Fall war. Kannst du mir vielleicht sagen was du mit den statischen Routinen meintest?

              So sollte es gehen:

              #ifndef MYCLASS_H
              #define MYCLASS_H
              
              #include <QMap>
              #include <QString>
              
              class MyClass
              {
                  static int MyStaticInt;
                  static QMap < QString, QString *> MyStaticMap;
              public:
                  MyClass();
              };
              
              #endif // MYCLASS_H
              
              #include "MyClass.h"
              
              int MyClass::MyStaticInt = 0;
              
              QMap<QString, QString*> MyClass::MyStaticMap;
              
              MyClass::MyClass()
              {
              }
              

              Vote the answer(s) that helped you to solve your issue(s)

              1 Reply Last reply
              1
              • K Offline
                K Offline
                koahnig
                wrote on last edited by
                #7

                Oder mit Q_GLOBAL_STATIC:

                #include "MyClass.h"
                
                #include <QSet>
                
                int MyClass::MyStaticInt = 0;
                
                QMap<QString, QString*> MyClass::MyStaticMap;
                
                Q_GLOBAL_STATIC (int, MyTotalGlobalInt);
                Q_GLOBAL_STATIC (QSet<QString>, MyTotalGlobalQSet);
                
                typedef QMap<QString,QString> MyMapT;
                Q_GLOBAL_STATIC(MyMapT,MyTotalGlobalQMap);
                
                MyClass::MyClass()
                {
                
                }
                

                So lässt es sich übersetzen.Musst aber einmal schauen, ob es da Nebeneffekte gibt.

                Wie geschrieben, die static als Member ist besser.

                Vote the answer(s) that helped you to solve your issue(s)

                T 1 Reply Last reply
                2
                • K koahnig

                  Oder mit Q_GLOBAL_STATIC:

                  #include "MyClass.h"
                  
                  #include <QSet>
                  
                  int MyClass::MyStaticInt = 0;
                  
                  QMap<QString, QString*> MyClass::MyStaticMap;
                  
                  Q_GLOBAL_STATIC (int, MyTotalGlobalInt);
                  Q_GLOBAL_STATIC (QSet<QString>, MyTotalGlobalQSet);
                  
                  typedef QMap<QString,QString> MyMapT;
                  Q_GLOBAL_STATIC(MyMapT,MyTotalGlobalQMap);
                  
                  MyClass::MyClass()
                  {
                  
                  }
                  

                  So lässt es sich übersetzen.Musst aber einmal schauen, ob es da Nebeneffekte gibt.

                  Wie geschrieben, die static als Member ist besser.

                  T Offline
                  T Offline
                  Throndar
                  wrote on last edited by Throndar
                  #8

                  Hallo @koahnig ,

                  wow vielen vielen Dank!

                  Mit den Beispielen konnte ich jetzt endlich den Aufbau nachvollziehen wie man static verwenden muss.

                  Jetzt ist nur noch ein Problem von mir offen an dem ich fest hänge. Ich kann jetzt meine Werte programmweit erreichen, nur komme ich aus dem QML Context nicht ran.

                  Ich habe ein Objekt der Klasse "UdpReceiver" in der Main erstellt und per

                  engine.rootContext()->setContextProperty("UdpReceiver", &uReceiver);
                  

                  im QML verfügbar gemacht. Jetzt kann ich aus dem QML auf die per Q_INVOKEABLE gekennzeichneten Funktionen zugreifen.

                  Die Klasse selbst habe ich (nachdem ich Konstruktor, Destruktor und CopyKontruktor erstellt habe) per

                  Q_DECLARE_METATYPE(UdpReceiver)
                  

                  im MOC bekannt gemacht. Das gleiche habe ich mit der Klasse "MovieClients" gemacht.

                  Bei dem Versuch jetzt per:

                  Q_PROPERTY(QMap<QString, MovieClient*> movieClientList MEMBER movieClients)
                  

                  die QMap für QML nutzbar zu machen bekomme ich als Meldung

                  
                  Lexical or Preprocessor Issue
                   
                  17:30: error: too many arguments provided to function-like macro invocation
                  qobjectdefs.h:62:9: note: macro 'Q_PROPERTY' defined here
                  

                  Ich kann das Programm zwar starten und bekomme auch im QML Context die "movieClientList" zur auswahl, aber scheinbar komplett ohne Ziel (per Console log liefert ein typeof "undefined".

                  Mache ich da einen Fehler beim Versuch die QMap aus dem QML erreichbar zu machen oder ist mein Ansatz komplett falsch an der Stelle?

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    Throndar
                    wrote on last edited by
                    #9

                    Nachtrag:

                    Das Problem mit den "to many arguments" scheint vom Komma in QMap zu kommen.

                    Ich habe darauf hin versucht per

                    typedef QMap<QString, MovieClient*> movies;
                    

                    das Komma zu umgehen. Das klappt soweit, nur meckert er jetzt

                    QMetaProperty::read: Unable to handle unregistered datatype 'movies' for property 'UdpReceiver::movieClientList'
                    
                    K 1 Reply Last reply
                    0
                    • T Throndar

                      Nachtrag:

                      Das Problem mit den "to many arguments" scheint vom Komma in QMap zu kommen.

                      Ich habe darauf hin versucht per

                      typedef QMap<QString, MovieClient*> movies;
                      

                      das Komma zu umgehen. Das klappt soweit, nur meckert er jetzt

                      QMetaProperty::read: Unable to handle unregistered datatype 'movies' for property 'UdpReceiver::movieClientList'
                      
                      K Offline
                      K Offline
                      koahnig
                      wrote on last edited by
                      #10

                      @Throndar

                      Die Makros haben ein Problem mit dem Komma, das hast du richtig erkannt.

                      Da musst du wohl noch qRegisterMetaType durchführen. Das zweite Beispiel sieht doch recht ähnlich mit deinem Fall:

                      typedef QString CustomString;
                      qRegisterMetaType<CustomString>("CustomString");
                      

                      Da muss ich auch gerade durchhangeln. ;)

                      Vote the answer(s) that helped you to solve your issue(s)

                      T 1 Reply Last reply
                      2
                      • K koahnig

                        @Throndar

                        Die Makros haben ein Problem mit dem Komma, das hast du richtig erkannt.

                        Da musst du wohl noch qRegisterMetaType durchführen. Das zweite Beispiel sieht doch recht ähnlich mit deinem Fall:

                        typedef QString CustomString;
                        qRegisterMetaType<CustomString>("CustomString");
                        

                        Da muss ich auch gerade durchhangeln. ;)

                        T Offline
                        T Offline
                        Throndar
                        wrote on last edited by Throndar
                        #11

                        Hallo @koahnig

                        super, das mit dem qRegisterMetaType hat mich schonmal einen riesigen Schritt weiter gebracht.

                        Ich habe jetzt sowohl die Klasse die ich erstellt habe als auch die QMap die Key und die Objekte (MovieClients) der eigenen Klassen enthält damit registriert und komme schonmal soweit das ich per

                        console.log(UdpReceiver.movieClientList)
                        

                        ein

                        qml: QVariant(QMap<QString,MovieClient*>)
                        

                        zurück erhalte.

                        (unter UdpReceiver ist der Name des Objekt unter dem ich es im QML Context verfügbar gemacht, movieClientList ist die Property unter der ich die QMap<QString, MovieClient*> bekannt gemacht habe).

                        Ich scheine also schon bis zum Objekt zu kommen in dem die QMap liegt, nur funktioniert der "normale" Zugriff auf die Werte scheinbar nicht. Im C++ Context würde ich jetzt ja beispielsweise mit

                        movieClients["192.168.100.94"]->name();
                        

                        auf die Daten die im MovieClient Objekt mit dem Key "192.168.100.94" an Eigenschat "name" liegen kommen, im QML kommt aber schon bei

                        console.log(UdpReceiver.movieClientList["192.168.100.94"])
                        oder
                        console.log(UdpReceiver.movieClientList.value("192.168.100.94"))
                        

                        Als Antwort ein:

                        undefined. (erste Anfrage)
                        bzw
                        TypeError: Property 'value' of object QVariant(QMap<QString,MovieClient*>) is not a function

                        zurück.

                        Ich gehe jetzt davon aus das der Fehler darin liegt das die QMap in einer QVariant liegt, aber wie kann ich auf den Inhalt einer QVariant zugreifen an der Stelle?

                        K 1 Reply Last reply
                        0
                        • T Throndar

                          Hallo @koahnig

                          super, das mit dem qRegisterMetaType hat mich schonmal einen riesigen Schritt weiter gebracht.

                          Ich habe jetzt sowohl die Klasse die ich erstellt habe als auch die QMap die Key und die Objekte (MovieClients) der eigenen Klassen enthält damit registriert und komme schonmal soweit das ich per

                          console.log(UdpReceiver.movieClientList)
                          

                          ein

                          qml: QVariant(QMap<QString,MovieClient*>)
                          

                          zurück erhalte.

                          (unter UdpReceiver ist der Name des Objekt unter dem ich es im QML Context verfügbar gemacht, movieClientList ist die Property unter der ich die QMap<QString, MovieClient*> bekannt gemacht habe).

                          Ich scheine also schon bis zum Objekt zu kommen in dem die QMap liegt, nur funktioniert der "normale" Zugriff auf die Werte scheinbar nicht. Im C++ Context würde ich jetzt ja beispielsweise mit

                          movieClients["192.168.100.94"]->name();
                          

                          auf die Daten die im MovieClient Objekt mit dem Key "192.168.100.94" an Eigenschat "name" liegen kommen, im QML kommt aber schon bei

                          console.log(UdpReceiver.movieClientList["192.168.100.94"])
                          oder
                          console.log(UdpReceiver.movieClientList.value("192.168.100.94"))
                          

                          Als Antwort ein:

                          undefined. (erste Anfrage)
                          bzw
                          TypeError: Property 'value' of object QVariant(QMap<QString,MovieClient*>) is not a function

                          zurück.

                          Ich gehe jetzt davon aus das der Fehler darin liegt das die QMap in einer QVariant liegt, aber wie kann ich auf den Inhalt einer QVariant zugreifen an der Stelle?

                          K Offline
                          K Offline
                          koahnig
                          wrote on last edited by
                          #12

                          @Throndar

                          Da muss ich passen. Mit QML habe ich selbst noch keine richtige Erafhrung.

                          Vote the answer(s) that helped you to solve your issue(s)

                          T 1 Reply Last reply
                          1
                          • K koahnig

                            @Throndar

                            Da muss ich passen. Mit QML habe ich selbst noch keine richtige Erafhrung.

                            T Offline
                            T Offline
                            Throndar
                            wrote on last edited by
                            #13

                            @koahnig

                            trotzdem Danke für deine Mühe, immerhin bin ich jetzt schon soweit das ich das was ich habe im QML habe... wenn auch eingepackt in einer QVariant aber schon mal überhaupt da.

                            Vielleicht hat ja noch jemand anders einen Tipp für mich :)

                            1 Reply Last reply
                            0

                            • Login

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