Qt ListBox Problem



  • Hallo. Ich versuche grade ein Programm zu entwickeln das eine "Log Box" hat. Das soll heißen das dort informationen zum Momentanen Step gemacht werden. Ich habe nun aber eine 2te classe etwas in die Listbox eintragen?? Ich habe mir in der GUI klasse eine Funktion geschrieben die daten loggt:

    void Farmcrawler::LogText(const QString logtext)
    {
        ui->textEdit->insertPlainText(logtext);
        ui->textEdit->insertPlainText("\n");
    }
    

    Danke für die Hilfe



  • Sorry, ich versteh wirklich nicht was du willst.

    Ich habe nun aber eine 2te classe etwas in die Listbox eintragen??

    Ein Fragezeichen reicht. Und bitte nochmal genau erklären, was dein Problem ist, der zitierte Satz ergibt einfach keinen Sinn.



  • hamburger schrieb:

    Hallo. Ich versuche grade ein Programm zu entwickeln das eine "Log Box" hat. Das soll heißen das dort informationen zum Momentanen Step gemacht werden. Ich habe nun aber eine 2te classe etwas in die Listbox eintragen?? Ich habe mir in der GUI klasse eine Funktion geschrieben die daten loggt:

    void Farmcrawler::LogText(const QString logtext)
    {
        ui->textEdit->insertPlainText(logtext);
        ui->textEdit->insertPlainText("\n");
    }
    

    Danke für die Hilfe

    Mach die Logfunktion zum Singleton, so dass jede Klasse drauf zugreifen kann oder übergib eine Referenz auf die Logklasse an jede Klasse die darauf zugreifen soll.
    Pattern zum Singleton findest ja hier genug.
    rya.



  • Scorcher24 schrieb:

    Mach die Logfunktion zum Singleton, so dass jede Klasse drauf zugreifen kann oder übergib eine Referenz auf die Logklasse an jede Klasse die darauf zugreifen soll.

    Singleton + ui beißt sich 😉
    Ein Widget kann halt nur an einer einzigen Stelle angezeigt werden. Wenn man da ein Singleton mit einflechtet, handelt man sich nur Probleme ein.

    Die bessere Lösung wäre eigentlich, eine eigene Logger-Klasse direkt von QObject abzuleiten. Das kann man schon als Singleton konzipieren. Diese Klasse sendet ein Signal "logged(const QString&)" aus, sobald was angehangen wurde. Das Signal mit QTextEdit::append() verbinden, und schon wird das textEdit automatisch aktualisiert, wenn was geloggt wird.

    Vorausgesetzt, wir liegen mit unserer Vermutung richtig, dass das ganze so ablaufen soll. Es kann ja auch sein, dass er einfach direkten Zugriff auf das ui->textEdit für eine andere Klasse freigeben will, dann wäre die Lösung "friend".



  • l'abra d'or schrieb:

    Scorcher24 schrieb:

    Mach die Logfunktion zum Singleton, so dass jede Klasse drauf zugreifen kann oder übergib eine Referenz auf die Logklasse an jede Klasse die darauf zugreifen soll.

    Singleton + ui beißt sich 😉
    Ein Widget kann halt nur an einer einzigen Stelle angezeigt werden. Wenn man da ein Singleton mit einflechtet, handelt man sich nur Probleme ein.

    Die bessere Lösung wäre eigentlich, eine eigene Logger-Klasse direkt von QObject abzuleiten. Das kann man schon als Singleton konzipieren. Diese Klasse sendet ein Signal "logged(const QString&)" aus, sobald was angehangen wurde. Das Signal mit QTextEdit::append() verbinden, und schon wird das textEdit automatisch aktualisiert, wenn was geloggt wird.

    Vorausgesetzt, wir liegen mit unserer Vermutung richtig, dass das ganze so ablaufen soll. Es kann ja auch sein, dass er einfach direkten Zugriff auf das ui->textEdit für eine andere Klasse freigeben will, dann wäre die Lösung "friend".

    Warum beisst sich das? Ich kann jederzeit ein Singleton in ein Programm integrieren, ich wüsste jetzt nicht warum sich das ausgerechnet bei UI-Programmen als schlecht darstellen sollte... hat QT keine globale LogKlasse oder sowas?
    friend hilft aber auch nur bedingt, wenn er auf ein existierendes Objekt zugreifen wil. Ich würde einfach das Log als Referenz übergeben, fertig.
    rya.



  • Wenn ich versuche die klasse abzuleiten bekomme ich einen Runtime error :S



  • hamburger schrieb:

    Wenn ich versuche die klasse abzuleiten bekomme ich einen Runtime error :S

    Es wäre gut wenn Du uns mal sagen könntest was genau Du machen willst.. deine Fragestellung ist nicht ganz klar.
    rya.



  • Scorcher24 schrieb:

    Warum beisst sich das? Ich kann jederzeit ein Singleton in ein Programm integrieren, ich wüsste jetzt nicht warum sich das ausgerechnet bei UI-Programmen als schlecht darstellen sollte... hat QT keine globale LogKlasse oder sowas?

    Prinzipiell ist ein Singleton kein Problem. Aber wenn ich meine Widget-Klasse als Singleton konzipiere, dann schon 😉
    Ein Widget-Objekt repräsentiert genau ein Element im Fenster. Ich kann dieses eine Objekt nicht an meherern Stellen anzeigen. Wenn ich in Qt ein Widget in ein anderes Layout lege, wird es automatisch aus dem alten entfernt. Wenn LoggerWidget ein Singleton ist, heißt dies auch dass das Widget in vollem Umfang als Singleton nutzbar ist, und das ist es leider nur mit Problemen.

    Ein weiteres Problem ist das rekursive Löschen von child-QObjects. Lege ich mein Singleton-Logger-Widget als child in ein Fenster, welches evtl. nur temporär existiert (z.B. ein Dialog über das Menü "Zeige Programm-Log"), wird das Programm beim nächsten "Logger::instance()->LogText()" SegFaulten 😉

    Mach ich nur "Logger::LogText()" static, brauch ich auch ein einziges statisches "ui"-Member. Und das geht noch schiefer, wenn ich mehrere Logger-Objekte erstellen will...

    Man stellt sich mehr Beine, als man davon profitiert. Auch vom Programm-Design her ist es besser, das eigentliche Loggen von der Loganzeige zu trennen.

    friend hilft aber auch nur bedingt, wenn er auf ein existierendes Objekt zugreifen wil. Ich würde einfach das Log als Referenz übergeben, fertig.

    Es kann doch sein, dass das ui (also eine Instanz der vom Designer+uic generierten Klasse) ein private-Member ist, und er einfach eine andere Klasse (z.B. MainWindow) hat, von der aus er direkt das ui->textEdit oder so verändern will. Dann hilft friend sehr wohl 🙂

    Nur ist meine Glaskugel gerade kaputt und den Hellsehkurs hab ich auch nicht bestanden - wir brauchen eindeutige, endgültige Infos vom OP 🙂



  • Ich dachte immer dass QT dem MVC-Konzept folgt? Sollte also der eigentlich logger nicht nur die Daten sammeln und die Darstellung ( das Widget ) in einer anderen Klasse erfolgen?

    Und wenn ich nur Zugriff auf textEdit will, dann reicht auch nen getter... da brauch ich nicht gleich friend :D.
    rya.



  • Scorcher24 schrieb:

    Ich dachte immer dass QT dem MVC-Konzept folgt? Sollte also der eigentlich logger nicht nur die Daten sammeln und die Darstellung ( das Widget ) in einer anderen Klasse erfolgen?

    Es gibt keinen Logger in Qt, deshalb gibt es da auch kein MVC 😛 Der schreibt sich doch selber nen Logger, deshalb liegt die Aufgabe des Designs auch bei ihm.
    Nur weil man Qt programmiert ist nicht alles was man macht automatisch MVC 😉

    Und wenn ich nur Zugriff auf textEdit will, dann reicht auch nen getter... da brauch ich nicht gleich friend :D.

    Klar, wenn man für alle den LineEdit als public exponieren will. Wenn es wirklich nur diese eine Klasse ist, hat man (meiner Meinung nach) bessere Kapselung, wenn man wirklich nur diese eine Klasse, die man ja selber schreibt, an die privaten Sachen ranlässt (ich weiß, kann man wieder weiterstreiten).
    Ciao (Yeah, Italien strauchelt, Frankreich streitelt, die WM kommt in Fahrt :D)



  • Ok für alle die nocht nicht so verstanden haben wie ich es meinte.

    Also ich habe eine Gui mit dem class name Farmcrawler. Dann habe ich noch eine Headerdatein wo meine eigene Klasse MeineClass drin ist. Weiterhin habe ich eine Funktion die in einem Extra Thread ausgeführt werden soll Funktion

    void StartIt()
    {
    MeineClass data;
    int Status;
    do
    {
       Status = Check_Status();
       if(Status == 1)
       {
           data.SetState(1);
           LogText("Aktion ist Fertig führe 2ten Schritt aus");
       }
       else
       {
           data.SetState(0);
           LogText("Muss noch ein wenig warten");
       }
    
    }
    while(1==1)
    }
    

    (Code frei erfunden war lediglich ein beispiel)

    So nun ist LogText eine Funktion der Gui Klasse (Farmcrawler). Wenn ich ein objekt Farmcrawler abc;
    anlegen würde wird ja nicht viel passieren, Da ich dann ja die GUI 2mal aufrufen würde. Nun ist meine frage wie kann ich aus der obrigen endlossschleife auf die Funktion LogText aus der Gui classe zugreifen.

    void Farmcrawler::LogText(const QString logtext)
    {
        ui->textEdit->insertPlainText(logtext);
        ui->textEdit->insertPlainText("\n");
    }
    

    Hoffe ihr versteht jetzt mein Problem



  • Wie ich bereits schrieb:
    Übergib an die jeweiligen Klassen eine Referenz auf die GUI-Klasse FarmCrawler oder trenne das Problem und arbeite mit Events. Sprich, du hast eine LogKlasse welche als Singleton implementiert ist und jedesmal wenn die eine Nachricht erhält, muss deine GUIKlasse drauf reagieren.
    Eine dieser Methoden würde ich wählen.
    rya.



  • Du musst in dem Fall (Arbeitender Thread vs. Mainthread (Gui-Thread)) sowieso andere Wege gehen, da du Gui-Zeichnen nur aus dem Gui-Thread heraus anstoßen kannst (textEdit->append() ist so eine Funktion). Am besten sendet deine Logger-Klasse (die selber kein Widget ist!) nur Signale aus, die in deiner Gui aufgefangen werden und einen Eintrag in einem separaten Logger-Widget (QTextEdit, QListView,...) einfügt. Wurde auch so schon empfohlen.
    Du musst aber die Logger-Klasse mit Mutex synchronisieren, da mehrere Threads gleichzeitig darauf zugreifen können und das Objekt verändern.



  • Mh wenn ich

    class Myclass : public Farmcrawler
    

    Dann bekomme ich einen Runtime Error bekommen



  • Kann mir jemand mal Bitte einen kleinen Beispielcode geben ich stehe auf dem Schlauch :S ich bin in Klassen noch nicht so gut :S



  • Dann solltest du das nachholen. Es hat für dich keinen Wert, wenn wir uns Mühe geben und ein funktionierendes Beispiel posten würden. C++-Grundlagen sind Pflicht, und dazu gehört auch das Wissen, wie Klassen funktionieren und wie man sie verwendet. Wie lernst du denn C++? Buch, Tutorial, Online-Kurs, Schule? Lass Anfangs einfach Gui (und auch Threads...) außen vor, das ist zu viel und bringt nochmal zusätzliche Spezialitäten (Events, Zeichnen, Layouts, Synchronisation, ...) die ein wirklich solides Wissen um C++ voraussetzen.



  • Ahh das ist ja nicht das Problem. Ich weiß wie Threads funktionieren und auch wie klassen. Jedoch habe ich bei der GUI ein Problem weil ich ja normal ein Objekt aus einer klasse erzeuge. Aber wie soll ich das machen wenn ich auf ein Vorhandenes zugreifen will?? Oder kann man Objekte weitergeben??

    Ich habe es mir selber beigebracht und dannach noch ergenzend ein Buch ( C++ a-z) gekauft. Ich bekomme soweit alles hin inc grundfunktionen von cpp. Danke für eure Hilfe :s ich habe ja alles soweit fertig das letzte element was fehlt ist halt die GUI. Ich hatte es schonmal mit der WINApI gemacht aber jedoch ist das zuviel code und man kann nicht so tolle sachen damit erstellen. Ich würde micht sehr doll über ein Beispiel freuen!



  • 1. Beispiel: Singleton

    #include <iostream>
    #include <string>
    
    class LoggerSingleton
    {
    private:
        LoggerSingleton() {}
        LoggerSingleton(const LoggerSingleton&) {}   
    
    public:
       void LogText(const std::string& text)
       {
          std::cout << "LogMessage : " << text << std::endl;
       }
    
       static LoggerSingleton& getInstance()
       {
          static LoggerSingleton OnlyOne;
          return OnlyOne;
       }
    };
    
    class foobar
    {
    public:
       foobar() 
       {
            LoggerSingleton::getInstance().LogText("Objekt erstellt");
       }
    };
    
    int main()
    {
      foobar foo;
    };
    

    Das hier ist das Beispiel wie man das über ein Singeton lösen kann. Ein Singleton ist eine Klasse, die nicht mehrfach instanziert werden kann. Man greift über einen statischen Getter immer auf das selbe Objekt zu. Natürlich muss das über einen Mutex auch synchronisieren. Aber Du weisst ja wie das geht :).

    2. Beispiel: Weitergabe des Loggers

    #include <iostream>
    #include <string>
    
    class Logger
    {
    public:
       void LogText(const std::string& text)
       {
          std::cout << "LogMessage : " << text << std::endl;
       }   
    };
    
    class foobar
    {
    public:
       foobar(Logger& log) 
        : m_log(log)
       {
            m_log.LogText("Objekt erstellt");
       }
    
    private:
       Logger& m_log;   
    };
    
    int main()
    {
       Logger log;
       foobar foo(log);
    };
    

    Hier wird eine Instanz der Klasse Logger erstellt und über den Konstruktor an foobar als Referenz weitergegeben. Eigentlich easy zu verstehen. foobar greift über die Referenz auf die Instanz der Klasse zu die in der Main erstellt wurde. Ergo landets im richtigen Logbuch.
    Mit QTEvents kann ich Dir leider keines liefern da ich ein anderes GUI Toolkit verwende, aber ich denke die Beispiele reichen um das zum laufen zu bringen.
    HTH
    rya.



  • Ok ich habe mich für die Singleton Variante entschieden. Doch wenn ich es aufrufe passiert nichts.



  • Liegt warscheinlich dadran das ich kein 2tes Objekt der Gui klasse erzeugen kann da es ja dann auf ein anderes objekt zugreift als das was ich möchte


Anmelden zum Antworten