QT: Welches Widget als "Container"?



  • Hallo zusammen,

    ich versuche gerade mit Qt warm zu werden und habe da noch meine Probleme, vor allem mit der Anordnung und Kombination von Widgets.

    Was ich erreichen möchte ist links ein TreeWidget mit ein paar Buttons oberhalb und eine wechselnde Detaiansicht auf der rechten Seite, getrennt durch einen Splitter.

    Soweit ich das verstehe benötige ich dazu zwei "Container", die ich durch Splitter horizontal teile und durch die Zuordnung eines weiteren Layouts an das Hauptwidget erhalte ich schon mal mein zweigeteiltes Fenster. In den linken Container kommen jetzt die Buttons + TreeWidget mit den entsprechenden Layouts. Das funktioniert jetzt endlich auch wie gewünscht.

    Im rechten Container möchte ich jetzt abhängig vom gewählten Knoten im Tree unterschiedliche Inhalte anzeigen, die idealerweise jeweils als eigenständige *.ui designt wurden.

    Welcher Container ist dafür geeignet und wie tausche ich den Inhalt?

    Ich hoffe ich habe mich einigermaßen verständlich ausgedrückt.

    Danke,
    temi



  • Der QSplitter ist schon ein geeigneter Container, mehr brauchst du nicht. Du lädst mit mit QUILoader dein QWidget und fügst es in den QSplitter ein.



  • Ah, das war mir nicht klar, dass das geht. Danke.

    Ich bin aber noch nicht sicher, ob QUILoader das richtige ist, deshalb eine kurze Erläuterung meiner Intention.

    Im Prinzip möchte ich so etwas wie das StackedWidget haben. Was mir aber gar nicht gefällt, ist, dass der gesamte zum UI gehörige Code in einer Klasse landet.

    Ich würde es vorziehen für jede "Page" (um bei der Nomenklatur des StackedWidgets zu bleiben) eine separate .h, .cpp und .ui zu erstellen, um die Entstehung einer "Superklasse" zu verhindern. Jede Page soll nur ihre Funktion erfüllen und kennen und in einem Bereich des Haupfensters angezeigt werden. Mal als Beispiel:

    "MainWindow": Hauptfenster für die Verwaltung der Pages
    "Orders": Alle Bestellungen anzeigen.
    "NewOrder": Neue Bestellung anlegen.
    "Customers": Alle Kunden anzeigen.
    "NewCustomer": Neuen Kunden anlegen.

    Wie kann ich so etwas in Qt sinnvoll lösen?



  • Einem QStackedWidget kann man zur laufzeit auch widgets hinzufügen
    http://doc.qt.io/qt-5/qstackedwidget.html#addWidget

    Dadurch kannst du deine Widgets auch komplett separat erzeugen/erstellen und dann einfach dem stack widget zuweisen



  • firefly schrieb:

    Einem QStackedWidget kann man zur laufzeit auch widgets hinzufügen
    http://doc.qt.io/qt-5/qstackedwidget.html#addWidget

    Dadurch kannst du deine Widgets auch komplett separat erzeugen/erstellen und dann einfach dem stack widget zuweisen

    Das ist ein guter Ansatz. Ich sehe gerade, dass es auch weitere Widgets gibt, die die Funktion "addWidget" haben, z.B. HBoxLayout. So habe ich es jetzt auch mal probiert, indem ich als "workspace" (der Bereich im Hauptfenster, der die Pages aufnehmen soll) ein HBoxLayout verwendet habe. Außerdem habe ich zwei weitere Widgetklassen "welcome" und "detail" komplett mit .h, .cpp und .ui angelegt.

    In der widget.h (das Hauptfenster) steht:

    class Widget : public QWidget
    {
            Q_OBJECT
    
        public:
            explicit Widget(QWidget *parent = 0);
            Welcome* welcome;
            Detail* detail;
            ~Widget();
    
        private slots:
            void on_pushButton_clicked();
    
        private:
            Ui::Widget *ui;
    };
    

    Und in der widget.cpp:

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        welcome = new Welcome(this);
        ui->workspace->addWidget(welcome);
        //detail = new Detail(this); // Erstes Problem...
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::on_pushButton_clicked()
    {
        detail = new Detail(this); // das ist Mist, ich weiß
        ui->workspace->removeWidget(welcome); // besser wäre removeWidget(current) ???
        ui->workspace->addWidget(detail);
        ui->workspace->update(); // ändert nix daran...
    }
    

    Das ist ziemlich schrottig, ich weiß. Nur zum Ausprobieren. Zumindest wird "welcome" beim Start sofort angezeigt und nach Buttonklick auch "detail" aber:

    Ich hatte das detailWidget zuerst im ctor von Widget erzeugt, aber dann wird es auch sofort in der linken oberen Ecke vom Hauptfenster angezeigt. Warum?

    Wenn ich es erst im pushButton_clicked erzeuge, dann wird es an der richtigen Stelle angezeigt, aber leider auch noch zusätzlich "welcome".

    Sorry für die dummen Fragen, aber ich bin totaler Qt-Anfänger und alle Tutorials, die ich mir angeschaut habe, gehen in eine andere Richtung.

    Gruß,
    temi



  • temi schrieb:

    Ich hatte das detailWidget zuerst im ctor von Widget erzeugt, aber dann wird es auch sofort in der linken oberen Ecke vom Hauptfenster angezeigt. Warum?

    Weil es in keinem Layout steckt. In dem Button Click Handler steckst du das in ein Layout.



  • Mechanics schrieb:

    temi schrieb:

    Ich hatte das detailWidget zuerst im ctor von Widget erzeugt, aber dann wird es auch sofort in der linken oberen Ecke vom Hauptfenster angezeigt. Warum?

    Weil es in keinem Layout steckt. In dem Button Click Handler steckst du das in ein Layout.

    Ok, es wird also sofort angezeigt, sobald es erzeugt wird. Schade. Ich hatte gehofft, die Pages in einen vector stecken zu können und jeweils das benötigte explizit anzuzeigen. Das geht dann wohl nicht so. Alternativ kann ich die Pages, so wie du vorgeschlagen hast, in das StackedWidget stecken, ich müsste dann nur die beiden Tasten zum Blättern abschalten. Edit: Sehe gerade, die werden zur Laufzeit eh nicht angezeigt...

    Edit2:

    Ich komme meinem Ziel näher. So gefällt mir das schon einigermaßen:

    MainView::MainView(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::MainView)
    {
        ui->setupUi(this);
        views["welcome"] = ui->workspace->addWidget(new Welcome);
        views["customers"] = ui->workspace->addWidget(new CustomerList);
    }
    
    MainView::~MainView()
    {
        delete ui;
    }
    
    void MainView::on_pushButton_clicked()
    {
        ui->workspace->setCurrentIndex(views["welcome"]);
    }
    
    void MainView::on_pushButton_2_clicked()
    {
        ui->workspace->setCurrentIndex(views["customers"]);
    }
    

Anmelden zum Antworten