1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

QT von anderer Klasse aus auf ui zugreifen

Dieses Thema im Forum "C/C++" wurde erstellt von ChriMo, 10. Januar 2018.

  1. ChriMo

    ChriMo Mitglied

    Hi
    Vereinfacht dargestellt:
    Habe ein ui mit einem QLabel.
    Vom Ablauf her:
    Nach Programmstart ui->label->setText("A");
    und dann ui->label->setText("B");

    Ist kein Problem (Klar, dass man nur "B" sieht - wie schon gesagt vereinfacht dargestellt)

    Nun möchte ich jedoch, dass ->label->setText("B"); aus einer Klasse "Teil_B" heraus aufgerufen wird.

    Und als Draufgabe: Pushbutton, der setText("C") bewirkt und dessen Slot in "Teil_B" beheimatet ist.

    Habe Folgendes versucht:
    mainwindow.h: Ganz normal, wie es der Creator erzeugt
    --------------
    teil_b.h:

    #ifndef B_H
    #define B_H
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>

    class Teil_B : public QObject
    {
    Q_OBJECT
    public:
    explicit Teil_B(Ui::MainWindow *dasUi);

    private slots:
    void on_pushButton_clicked();

    private:
    Ui::MainWindow *UIVonMain;

    };

    #endif // B_H
    -----------------
    mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "teil_b.h"
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    ui->label->setText("A");
    // ui->label->setText("B"); Das in Klasse "Teil_B" verschieben.
    // Und hier sollte Teil_B aufgerufen werden. Doch wie?
    Teil_B (*ui) ; //Wird anscheinend ignoriert

    }


    ----------------------
    teil_b.cpp:

    #include "teil_b.h"

    Teil_B::Teil_B(Ui::MainWindow *dasUi)
    {
    qDebug()<<"B gestartet";

    UIVonMain = dasUi;
    UIVonMain->label->setText("B");

    }

    void Teil_B::eek:n_pushButton_clicked()
    {
    qDebug()<<"geklickt";
    UIVonMain->label->setText("C");
    }


    Das Programm wird zwar ausgeführt, Teil_B jedoch anscheinend vollkommen ignoriert:
    Nicht mal qDebug()<<"B gestartet"; wird angezeigt.


    LG
    ChriMo
     
  2. cwriter

    cwriter Erfahrenes Mitglied

    Ehrlich gesagt verstehe ich dein Problem nicht so ganz (liegt teilweise am Fehlen von mainwindow.h). Das UI sollte nicht von Teil_B gesteuert werden, denn nur MainWindow verwaltet es.

    Code (C++):
    1. class Teil_B : public QObject
    2. {
    3.     Q_OBJECT
    4. public:
    5.     Teil_B() = default;
    6.     Teil_B(QLabel* label, QPushButton* button)
    7.     {
    8.         setLabel(label);
    9.         setButton(button);
    10.     }
    11.  
    12.     void setLabel(QLabel* label) { m_label = label; m_label->setText("B"); }
    13.     void setButton(QPushButton* button) { m_pb = button; connect(m_pb, SIGNAL(clicked()), this, SLOT(onPushButtonClicked())); }
    14.  
    15. }
    16. private slots:
    17.     void onPushButtonClicked()
    18.     {
    19.         //Whatever
    20.     }
    21. private:
    22.     QLabel* m_label;
    23.     QPushButton* m_pb;
    24. };
    25.  
    26.  
    27. MainWindow::MainWindow(QWidget *parent) :
    28. QMainWindow(parent),
    29. ui(new Ui::MainWindow)
    30. {
    31. ui->setupUi(this);
    32.  
    33. ui->label->setText("A");
    34. m_teil_B.setLabel(ui->label);               //Member in der Form Teil_B m_teil_B;
    35. m_teil_B.setButton(ui->pushbutton);
    36. }
    Dein Problem ist, dass du ja irgendeinen Konstruktor hinschreibst, aber kein zugehöriges Objekt erstellst. Generell scheinst du aber ein ziemlich kompliziertes Management im Sinn zu haben. In der Regel ist es am klügsten, genau eine Klasse die Anzeige machen zu lassen, und der Rest macht die echte Arbeit.

    Gruss
    cwriter
     
  3. ChriMo

    ChriMo Mitglied

    Der Grund ist, dass es sich hierbei um ein ziemlich komplexes bauphysikalisches Programm handelt:
    Verschiedene Berechnungsteile, die zum Teil voneinander abhängen, jedoch mit einer gemeinsamen Darstellung (Sowohl Ergebnisse als auch Eingaben), die komplizierte Struktur ergibt sich daraus.
    Wie bekomme ich es hin, dass es so funktioniert? - Dann wär ich happy.

    LG
    Christoph
     
  4. cwriter

    cwriter Erfahrenes Mitglied

    Ok, also hast du verschiedene Berechnungsteile. Willst du parallelisieren? Dann geht es so "offiziell" nicht. Oft funktioniert(TM) es zwar, aber Qt wird dich mit Warnungen eindecken, wenn verschiedene Threads auf das GUI zugreifen. Die Lösung da: Signals & Slots. (Signal wird von Worker-Threads emittiert und mit einem Slot im Displaythread verbunden).
    Willst du nicht parallelisieren? Dann hängt deine GUI wahrscheinlich sehr oft, vor allem aber fehlt ein guter Grund, die Arbeit in Teile zu spalten.



    Wie denn?
    Was funktioniert an meinem Beispielcode nicht?

    Das Problem bei deinem Code ist schlicht, dass dein freistehender Konstruktor nichts machen kann, weil er keiner Instanz zugeordnet bzw., falls es ein Member der Klasse sein soll, schlicht schon initialisiert ist. Also entweder erstellst du eine lokale Instanz ("Teil_B b(ui)") oder du hast eine Member und reinitialisierst durch Kopie ("m_b = Teil_B(ui)") oder du machst es wie im Beispiel mit settern.

    Am besten überdenkst du dein Design aber komplett. Ich habe schon ein paar mal mit Qt gerarbeitet und du kannst mir glauben, dass die UI immer von Anfang an entkoppelt sein sollte. Es gibt sonst immer irgendwelche Probleme.

    Gruss
    cwriter
     
  5. ChriMo

    ChriMo Mitglied

    Wenn man Qtabwidgets verwendet, schreibt QT den Code leider für alle Tabs in die selbe Klasse.
    Ich habe z.B. in tab1 Tabellen etc. und in tab2 auch Tabellen etc.
    Und als Ergebnis einen Haufen mit Code für alle.
    Ich möchte für jeden tab eine eigene Klasse haben, in der auch der ui-Zugriff auf die Objekte des Tabs möglich ist.

    LG
    ChriMo
     
  6. cwriter

    cwriter Erfahrenes Mitglied

    Nope, eigentlich nicht, QTabWidget hat einzelne QWidgets als Tabs. Diese kannst du auch mit einer eigenen Klasse ersetzen.


    Ein Haufen Code ist ein Ergebnis? Ich verstehe nicht, was du meinst.

    => Eigenes QWidget

    Nein, willst du nicht. Wie soll dann die Hierarchie aussehen? Das MainWindow ruft eine Klasse auf, die dann zurück zum MainWindow geht und ein anderes Element aufruft, usw.? Und in der Zwischenzeit wird das Fenster nicht neu gezeichnet?

    Nochmals: Logik und Darstellung müssen immer getrennt sein. Du kannst im MainWindow per Signal die Logik starten. Ist diese fertig, emittiert sie ein Signal, dass sie fertig ist, und die verbundenen Widgets ihre Daten ziehen können.

    Gruss
    cwriter
     
  7. ChriMo

    ChriMo Mitglied

    Oh weh, da hab ich die QTabWidgets falsch verstanden:
    Habs im Designer kreiert, über re Maustaste tabs hinzugefügt und diese mit Dingen aus der Widget-Box gefüllt.
    Dann mit re-Maus Slots hinzugefügt, und die landen alle in der Klasse, in der auch das QTabWidget ist, egal um welchen tab es sich handelt.
    Das meinte ich mit "Haufen" - meinen Code hab ich auch noch dazu geschrieben.
    Der "Haufen" hat mich gestört, irgend jemanden in irgend einem Forum auch, und der hat die Antwort bekommen, dass das eben so ist und nicht anders geht.
    Wo das war, weiß ich nicht mehr, jedenfalls hat dort niemand widersprochen und ich hab es unreflektiert übernommen.
    Danke, dass Du so prompt darauf reagiert hast und durch meinen Beitrag der Mist nicht weitergegeben wird.
    Hab ich es richtig verstanden:
    Im Designer erstelle ich ein QTabWidget ohne Tabs
    Ich erzeuge neue Designer-Formularklasse/Widget und füge diese per Code (->addTab(new ....) ) im QTabWidget ein.
    Der Weg, im Designer erstellten Tabs Klassen zuzuordnen ist nicht möglich?

    LG
    ChriMo
     
  8. cwriter

    cwriter Erfahrenes Mitglied

    Doch, über Rechtsklick auf das QTabWidget, dann "Page 1 of 2" (Zahlen können abweichen; es ist immer der Selektierte Tab (weiss nicht, wie es auf Deutsch angeschrieben ist)), und dann auf "Promote to", wo du eine andere Klasse angeben kannst.

    Immer gerne. Dafür ist ja das Forum da :)

    Die Slots von Qt sind tatsächlich viel mächtiger, als der Designer es vermuten lässt. Aber ja: Mach soviel wie möglich im Designer. Manuell geht es auch, aber man hat viel länger damit.

    Gruss
    cwriter
     
Die Seite wird geladen...