GUI-Komponenten in QT-Creator von beliebigen C++ Dateien aus ansprechen



  • Hallo Community,

    wenn man sich in QT-Creator ein QT-Widget erstellt, gibt es ja eine vorgefertigte h, cpp und ui Datei. Die cpp Datei sieht z.B. so aus:

    #include "ServerWindow.hpp"
    #include "ui_ServerWindow.h"
    
    ServerWindow::ServerWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::ServerWindow) {
        ui->setupUi(this);
    }
    
    ServerWindow::~ServerWindow() {
        delete ui;
    }
    

    Dort kann man GUI-Komponenten z.B. mit ui -> textLabel-> setText("Hallo"); ansprechen. Also ist in dem "ui" ja irgendwie die ui-Datei initialisiert.
    Meine Frage ist, wie ich bestimmte ui-Dateien in anderen C++ Dateien initialisieren kann, damit ich von da aus GUI-Komponenten ansprechen kann. Also dass ich quasi in einer extra erstellten C++ Datei mit ui -> eine Komponente aus einer ui-Datei ansprechen kann?

    Danke für alle Antworten!



  • @Coop4Free sagte in GUI-Komponenten in QT-Creator von beliebigen C++ Dateien aus ansprechen:

    Also ist in dem "ui" ja irgendwie die ui-Datei initialisiert

    Eine Datei ist initialisiert?





  • Werf mal einen Blick in deinen build ordner. Aus der .ui file wird eine header Datei generiert.

    class Ui_Window
    {
    public:
        QGridLayout *gridLayout;
        
         void setupUi(QWidget *Window) {}
    
    };
    
    namespace Ui {
        class Window: public Ui_Window {};
    } // namespace Ui
    
    

    In deiner header Datei (die automatisch generierte) hast du noch sowas:

    namespace Ui
    {
        class Window;
    }
    

    Mit ui(new Ui::ServerWindow) erzeugst du ein neues Objekt deiner Klasse (die du wohl ServerWindow genannt hast) und speicherst es in dem Member ui und da alle Gui Elemente ohne Hirachie da als pointer drin ligen, kannst du dementsprechend darauf direkt zugreifen mit ui->textLabel.

    Wenn du aus einer anderen Klassen Zugriff darauf haben möchtest, könntest du z.B. das Objekt an eine andere Klasse weiterreichen. Wobei du dich grundsätzlich fragen solltest, ob das wirklich nötig / sinnvoll ist. Wenn du von KlasseXYZ aus wissen willst, wann button xyz gedrückt worden ist, kannst du dafür ja das Signal Slot System nutzen und in deiner ServerWindow Klasse (also deiner eigenen, nicht der UI::ServerWindow) ui->button->buttonPressed mit deiner gewünschten Klasse connecten.



  • @Leon0402

    Danke für deine Tipps, es hat geklappt 🙂



  • @Leon0402 sagte in GUI-Komponenten in QT-Creator von beliebigen C++ Dateien aus ansprechen:

    Wenn du von KlasseXYZ aus wissen willst, wann button xyz gedrückt worden ist, kannst du dafür ja das Signal Slot System nutzen und in deiner ServerWindow Klasse (also deiner eigenen, nicht der UI::ServerWindow) ui->button->buttonPressed mit deiner gewünschten Klasse connecten.

    Gibt es auch eine Möglichkeit ein Signal von einer beliebigen Klasse, von mir aus myClass mit einem Slot der Klasse MainWindow zu connecten?

    z.B. will ich in einer Methode der Klasse myClass einen Wert an die Klasse MainWindow übergeben.

    Und wie sieht es eigentlich mit einer QMessageBox aus? Das lässt sich in der myClass auch nicht erstellen.



  • Das solltest du umgekehrt machen (da eine eigene [Logik-]Klasse keinen direkten Zugriff auf die UI haben sollte):

    • in myclass einen SLOT anbieten
    • die UI-Klasse verbindet sich mit diesem SLOT und wertet dann die Übergabeparameter aus

    Hast du die entsprechenden Includes eingebunden (aber auch hierfür gilt das obengeschriebene)?



  • Irgendwie habe ich gerade total den Knoten im Kopf.

    Nehmen wir als Beispiel das Beispiel aus unserem anderen Thread (https://wiki.qt.io/Download_Data_from_URL/de)

    In der Methode fileDownloaded() der Klasse FileDownloader habe ich ein paar Zeilen ergänzt (siehe Kommentar):

    void FileDownloader::fileDownloaded(QNetworkReply* pReply)
    {
        m_WebCtrl.setStrictTransportSecurityEnabled(true);
    
        m_DownloadedData = pReply->readAll();
    
        //meine Anweisungen:
        std::string text = pReply->readAll().toStdString();
        QString conv;
        conv = conv.fromStdString(text);
        //wie kann ich den Inhalt von  conv  zum  MainWindow  übermitteln um es z.B. in einem Label anzuzeigen?
       
    
        //emit a signal
        pReply->deleteLater();
        emit downloaded();
    }
    

    und so sieht die connect()-Anweisung im Konstruktor aus:

    FileDownloader::FileDownloader(QUrl imageUrl, QObject *parent) :
        QObject(parent)
    {
    
    
        connect(&m_WebCtrl, SIGNAL (finished(QNetworkReply*)), SLOT (fileDownloaded(QNetworkReply*)));
    
        QNetworkRequest request(imageUrl);
        request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
        m_WebCtrl.get(request);
    }
    

    Wie würde man es am elegantesten lösen?



  • Eigentlich genau so wie mit dem downloaded-SIGNAL (bzw. noch passende Parameter hinzufügen).

    ABER in diesem Fall kannst du ja sogar komplett darauf verzichten, denn diese Konvertierung (und Anzeige) kannst du doch direkt in der mit der downloaded-verbundenen Funktion loadImages (bzw. wie immer diese bei dir heißt) durchführen:

     void MainWindow::loadImage() {
        const QByteArray& data = m_pImgCtrl->downloadedData();
    
        QString text = QString::fromLatin1(data.data()); // <-- performanter als über std::string zu gehen!
       // todo: show text in label ... 
    }
    

    (oder alternativ eine andere Kodierung wie `QString::fromUtf8(...)' - am besten natürlich anhand des Headers auswerten!)

    Anscheinend hast du doch noch nicht so ganz das SIGNAL-SLOT-Prinzip verstanden?!



  • Danke, Dein Code funktionert! Nur mit der anderen Möglichkeit also per Signal wüsste ich nicht wie ich das hinbekomme. Aber vielleicht kriege ich das ja noch hin, wenn nicht wäre das echt peinlich für mich.


Anmelden zum Antworten