C++ Qt Creator / Signale Slots / Toolbar /

PEASANT KING

Commander
Registriert
Okt. 2008
Beiträge
2.412
Hallo Leute,

ich muss hier noch mal die Erfahreren von euch fragen.

In Qt gibt es ja die sogenannten Signale und Slots ich versteh das als eine Art Observer / Observable.
Ich habe mir eine schöne GUI zusammen gesetzt diese enthält eine Toolbar mit Buttons. Das ganze liegt in einer "Main.ui" Datei.
Meine Anwendung besitzt ein Modul Kundenverwaltung, was eine eigene "Kunden.ui" Datei besitzt sowie eine Header Datei und eine .cpp

Wie kann ich es möglich machen, dass die Button präsent in meiner Toolbar nur die Action ausführen, die gefragt ist, also wenn ich im Kundendialog bin sollen z.B. die eingegebenen Daten im Dialog Kunden gespeichert werden,
wenn ich mich allerdings im Dialog xyz befinde sollen die Daten aus xyz gespeichert werden. Dazu benötige ich ja viele Slots allerdings nur ein Signal richtig ?

Ich denke es ist eher so eine design technische Frage meinerseits.

Ich bin kein studierter Programmierer muss ich dazu sagen, sondern Jemand der sich selber alles bei bringt, also bin ich auch kein Profi was Design Pattern oder Software Design in allgemeinen angeht.

Grüße DJ
 
Hi DJ,

des Design hast du nur anhand von Qt gemacht wie ich verstanden habe. Die .cpp ist eine C++ Datei. Normalerweise implementierst du die Qt in z.B. Visual Studio in dein C++ Programm und verwaltest die Buttonbefehle als Event.

Design ist nur die Oberfläche.

Gruß Graph
 
Ne ich habe das ganze in Qt Creator gemacht. Also ich programmiere die C++ Dateien auch in Qt Creator.

Um mein Problem noch mal genauer zu beschreiben, mein Ziel ist es eine zentrale Toolbar zu haben, über die ich einzelne GUI Teile die sich in verschiedenen .ui Files befinden zu steuern.
Wie wird sowas programmier technisch umgesetzt ?

Es gibt halt bei mir ein MainWindow und dann mehrere Widgets die z.B. im Moment per Button Click hinzugefügt oder entfernt werden im MainWindow auf ein QTabWidget.
Kann auch gern mal ein Screenshot anhängen.
 
Erstmal machst du imho mit QT und QTCreator alles richtig und ich würds auch als Einstieg empfehlen.

Ich denke es ist eher so eine design technische Frage meinerseits.
Das würd ich nicht so sehen - es ist eher die Frage wie man SIGNAL/SLOT nun richtig verwendet.

Dein Konzept ist etwas ungewöhnlich: Du hast eine Toolbar und dort zB einen Button. Dieser Button soll abhängig davon, was für eine andere Darstellung deine UI zur Zeit hat jeweils Unterschiedliche Funktionen realisieren? Das würde ich eigtl nicht empfehlen aber ist natürlich alles möglich.

Signale und Slots sind wirklich ganz simpel und Dinge wie 'Observer / Observable' muss man dafür nicht kennen oder verstehen.
Stell dir vor ein Signal ist wie ein Funktionsaufruf. Allerdings ist die Verbindung nicht 1:1 also ein Signal immer genau auch ein Aufruf eines Slots sondern es gibt zu jedem Signal 0 bis auch N Slots (=Funktionen) die dann nacheinander statt finden. Soweit reicht das vom Verständnis her, solange du die Signale und Slots nicht über Threadgrenzen hinweg nutzt, was aber auch nicht schwierig wäre.

über die ich einzelne GUI Teile die sich in verschiedenen .ui Files befinden zu steuern.
Wie wird sowas programmier technisch umgesetzt ?
Deine Toolbar sollte ein eigenes Widget sein. Dh du hast wahrscheinlich im QTCreator Rechtsklick auf dein Projekt und 'Add new' und danach links QT (und nicht C++) gewählt und danach rechts 'QT Designer Form Class' - stimmt das so? Dann sollte es jetzt zB Toolbar.ui, Toolbar.cpp und Toolbar.h geben. Die ui kannst du nun mit dem QTDesigner grafisch bearbeiten.
Fügst du der Toolbar.ui nun einen QButton hinzu machst du einen rechtsklick drauf und wählst 'Go to slot---' und wählst das Signal 'clicked'.
Dadurch wird nun in Toolbar.h und .cpp jeweils Signatur und Implementierung der on_button_clicked() angelegt.
Diese Funktion wird nun immer aufgerufen wenn man den Button klickt.
Du könntest hier also schonmal
Code:
std::cout << "Toolbar button was presssen!" << std::endl;
probieren.
Anschließend willst du dieses Ereignis ja nun weiter reichen.
Dh deine Toolbar braucht ein signal, was du in der Toolbar.h erstmal anlegen musst zB so:
Code:
signals:
    void myFirstButtonWasPressed();
Anschließend kannst du dieses Signal 'auslösen' indem du innerhalb von on_button_clicked() noch nach dem std::cout ergänzt:
Code:
emit myFirstButtonWasPressed();
Was du nun machen musst ist das SIGNAL myFirstButtonWasPressed() mit einem SLOT eines deiner anderen Widgets zu verbinden mittels CONNECT.
Dies ist natürlich ganz allgemein erstmal nur möglich für ein Objekt, welches sowohl die Toolbar ALS AUCH die anderen Widgest kennt!
Dh die Toolbar als auch deine anderen Widgets sind ja wahrscheinlich in einem QMainWindow oder QWidget angesiedelt.
In diesem 'Mutterfenster' kannst du nun das CONNECT durchführen.
Das sieht zB so aus:
Code:
connect(ui->toolbar, SIGNAL(myFirstButtonWasPressed()), ui->myFirstOtherWidget, SLOT(slot_toolbarMyFirstButtonWasPressed()))
Dh dein anderes Widget 'myFirstOtherWidget' braucht nun in seiner .h einen
Code:
public slot:
    slot_toolbarMyFirstButtonWasPressed();
und natürlich in der .cpp auch eine Implementierung.
Diese könnte zB erstmal auch wieder nur aus std::cout bestehen.




EDIT:
Das ganze von einer Toolbar aus zu realisieren ist also ohne großen Aufwand möglich aber wie gesagt trotzdem etwas ungewöhnlich/umständlich.
Einfacher wäre wenn ein Widget (ui, h, cpp) sowohl den Button hat also auch direkt den Code der ausgeführt werden soll wenn man ihn drückt. Bei dir wird ein Button gedrückt und diese Info dann erstmal an andere Widgets weiter gereicht.
 
Zuletzt bearbeitet:
Nur falls das nicht klar ist: Du kannst Signale ja zur Laufzeit verbinden und auch wieder trennen. Eine Möglichkeit wäre also das Signal immer nur mit den jeweiligen Slots des gerade geöffneten Dialogs zu verbinden.
 
Vielen Dank für diese lange Erklärung bin dir echt dankbar @kuddlmuddl grundsätzlich habe ich Signale und Slots auch vorher schon verstanden, du hast es mir nun noch mal ausführlicher beschrieben, allerdings beschreibe ich dir jetzt mal wie meine Anwendung aussieht:

Also zunächst einmal gibt es eine Klasse "xyz.cpp" mit einer "xyz.h" und einer "xyz.ui" soweit so gut dies ist mein Mainframe oder in Qt Widget genannt, an dieser Stelle sry ich habe früher mit Java angefangen und viele Jahre mit Java programmiert bevor ich mich dann an C++ ran gewagt habe es aber zu viel Aufwand fand mit wxWidgets mir die GUI manuell zusammen zu programmieren etc. und dann dachte, da auch Crossplatform möglich zu Qt zu wechseln.
Also in dem besagten Mainframe liegt also eine zusammen gebastelte OutlookBar auf der linken Seite und rechts daneben gibt es ein QTabWidget und oben eine Toolbar siehe Bild nun werden beim Buttondruck links in der Explorerleiste Tabs hinzugefügt oder eben über den Tab Close Button geschlossen funktioniert wunderbar mein Ziel ist es jetzt nur noch wenn Tab ABC auf ist soll der Inhalt aus ABC gespeichert werden gelöscht werden oder sonst was und wenn ich in EFG Tab bin soll nur in EFG Dinge gespeichert werden ect.

Ist meine Logik falsch ?

Ich habe es im Moment so gelöst, das ich Abfrage auf welchem Tab der Focus liegt und dann die Action ausgeführt ist die dem Tab zu geordnet ist. Also eine Lösung habe ich für das Problem, aber ist diese Lösung praktikabel ?
Macht man das so?

UPDATE:

Code:
connect(ui->mainTabWidget,SIGNAL(currentChanged(int)),this,SLOT(changeToolBarButtons()));

/**
 * Checks which tab is active and then changes mainToolBar actions
 * depending on which tab is the current tab.
 *
 * @brief HebManager::changeToolBarButtons
 */
void HebManager::changeToolBarButtons()
{
    int index = ui->mainTabWidget->currentIndex();
    QString tabName = ui->mainTabWidget->tabText(index);

    if(tabName == "Kundenstamm") {
        ui->actionNew->setEnabled(true);
        ui->actionOpen->setEnabled(true);
        ui->actionSave->setEnabled(true);
        ui->actionCopy->setEnabled(true);
        ui->actionCut->setEnabled(true);
        ui->actionDelete->setEnabled(true);
    } else {
        ui->actionNew->setEnabled(false);
        ui->actionOpen->setEnabled(false);
        ui->actionSave->setEnabled(false);
        ui->actionCopy->setEnabled(false);
        ui->actionCut->setEnabled(false);
        ui->actionDelete->setEnabled(false);
    }
}
 

Anhänge

  • app.png
    app.png
    64,3 KB · Aufrufe: 235
Zuletzt bearbeitet:
Am WE kann ich dir nochma ausführlicher antworten.. wenn du noch Infos oder Code hast immer her damit.
 
Zurück
Oben