Seite 1 von 1

Viele Buttons, ein Context-Menü, zwei Actions

Verfasst: 23. Juni 2010 23:55
von Pixtar
Hallo an alle,

ja der Titel des Themas ist Programm. Ich habe viele Buttons, die jeweils ein und das selbe Context-Menü verwenden sollen, in dem wiederum jeweils nur zwei Actions vorhanden sind.
Das QMenu habe ich dem PushButton per setMenu zugewiesen.

Wenn der Slot durch die Action aufgerufen wird, komm ich durch:

Code: Alles auswählen

dynamic_cast<QMenu*>(sender()->parent());
bis zum QMenu vor, aber dann ist Schicht im Schacht. Denn die Doku sagt:
Ownership of the menu is not transferred to the push button.
Weis da jemand Rat, wie ich an den Ursprungsort der Signalkette gelang? (QPushButton)

Grüße Pixtar

Re: Viele Buttons, ein Context-Menü, zwei Actions

Verfasst: 24. Juni 2010 08:20
von franzf
Pixtar hat geschrieben:Ich habe viele Buttons, die jeweils ein und das selbe Context-Menü verwenden sollen, in dem wiederum jeweils nur zwei Actions vorhanden sind.
[...]
... Schicht im Schacht. Denn die Doku sagt:
Ownership of the menu is not transferred to the push button.
Sei froh, dass die Besitzverhältnisse nicht verändert werden, sonst könntest du ein und dasselbe Menu nicht verschiedenen Buttons zuordnen. Ist wie mit Widgets in nem Layout; Lege Widget in Layout a, danach in Layout b, letzteres entfernt es aus Layout a...

Die Lösung? Kommt drauf an. Z.B. ohne dem Button Menu, dafür das clicked() über einen QSignalMapper auf einen Slot legen, über den du den Button identifizieren kannst und speicherst den als Member. Dort zeigst du selbständig dein Menu an. Wird eine Action ausgelöst, kannst du über den gerade gespeicherten Button-Zeiger wieder rückschließen, was du jetzt machen willst.

Verfasst: 24. Juni 2010 21:59
von Pixtar
Du schreibst ich solle das QMenu kicken, aber ich hätte das schon gerne im Button eingebettetk, denn es sollen ja mehrere Optionen bei Buttonclick vorhanden sein.

Zusammen bekomme ich das irgendwie nicht gehandelt, vorallem da die Actions dann trotzdem in einer Liste vorhanden sein müssten.

Die Problematik ist folgende: Es sind X Elemente, die alle den selben Button mit dem selben Menü haben sollen. X ist hierbei dynamisch, sprich es kann zur Laufzeit verändert werden.
Die Menüitems sollen dann immer ein und die gleich Funktion mit unterschiedlichen Parametern aufrufen - basierend auf den Button bei dem das Menüitem geklickt worden ist.

Der QSignalMapper scheint eine gute Option dafür zu sein, jedoch versagt er auf der Strecke. Denn mit den vorhanden Methoden kommt man meines Erachtens nicht weit.

Code: Alles auswählen

int i = 0;

QPushButton *my1Button = new QPushButton( QString::number(i), this );
QMenu *myMenu = new QMenu;
my1Button ->setMenu( myMenu );
QAction *myFirstAction= new QAction( myMenu );

QString myText = "Schön";
QSignalMapper *myMenuMapper = new QSignalMapper(this);
connect (myFirstAction, SIGNAL( toggled() ), myMenuMapper, SLOT( map() ) );
myMenuMapper->setMapping( myFirstAction, myText );
connect( myMenuMapper, SIGNAL( mapped(const QString &) ), this, SIGNAL( getTheSenderVal(const QString &) ) );

//---\\

int i = 1
QPushButton *my2Button = new QPushButton( QString::number(i), this );
...
//Und jetzt? Bräuchte ich ein weiteres QMenu und weiter QActions, die erstellt werden müssten.. sinnlos -.-
Zum einen kann ich in diesem Fall das vorhandene Mapping für den QSignalMapper nicht aufheben, oder? Soetwas wie myMenuMapper->removeMapping(myFirstAction) gibt es nämlich nicht ..
Zum anderen ist der QSignalMapper nur für Komponenten gedacht die mehrfach vorhanden sind. Nun und da ich ja gerne nur ein QMenu mit insgesamt zwei verschiedenen QActions haben will fällt QSignalMapper aus dem Rahmen. Denn dann müsste ich bei jedem Buttonclick ein anderes QMenu öffnen ODER das vorhandene QMenu mit den anderen QActions ersetzen. UND das klingt wirklich nach einem Workaround.

Verfasst: 24. Juni 2010 22:12
von franzf
Pixtar hat geschrieben:Du schreibst ich solle das QMenu kicken, aber ich hätte das schon gerne im Button eingebettetk, denn es sollen ja mehrere Optionen bei Buttonclick vorhanden sein.
Ich hab doch nicht gesagt, dass du das menu kicken sollst! Nur dass du nicht das Menu via QPushButton::setMenu() setzen sollst (ok, vllt. nicht so direkt, Button Menu war meine Formulierung). Und nicht die QAction soll in den QSignalMapper sondern der QPushButton, genauer dessen clicked()-Signal. Ich will nämlich den aktuell geklickten Button, der das Menu anzeigen soll und für den dann die aktivierte Action gelten soll (!) über dessen clicked() identifizieren. Und wenn du button.setMenu() machst, kommt kein clicked() mehr, es geht nur das Menu auf. Und wenn du nur ein einziges QMenu für alle Buttons haben willst, musst du irgendwo den Button herbekommen, der das Menu angezeigt hat, oder? (hast ja gemerkt, dass es über die parent()s nicht geht...)

Nun kannst du nämlich bei dem gemappten clicked() den Button speichern und das Menu an entsprechender Stelle (selber) anzeigen. Die beiden Actions sind connected auf Slots, in denen du dann, wenn sie ausgelöst werden, nur auf den gespeicherten Button zugreifen brauchst, um an deinen Auslöser zu kommen.

Jetzt ist es auch klar, dass du zum Entfernen eines Mappings die dafür vorgesehene Methode verwenden kannst ;) (Ich nehme an, du möchtest einfach einen Button entfernen, oder?)

Ich hoffe das war jetzt klarer.

Verfasst: 25. Juni 2010 14:57
von RHBaum
Warum alles so umstaendlich ?

Rein vom Design:

Dein button praesentiert doch nun nicht nur einen Button, der eine Bestimmte aktion startet, sondern er definiert ja noch was eigenes, was die Aktion parametrisiert ...

Warum also nicht ne neue Buttonklasse ?

Ableiten von QPushButton oder was weiss ich ...

Im Konstruktor den "Parameter" mit angeben.
Den Paramter als Member halten ...

ContextMenu gleich mit anlegen

Im Button selber die Events die du brauchst (clicked, pressed, die menuhaendler) abfangen mit dem parameter versehen und als signal emitten ... und voiala, stattet der button seine events/Signale selber mit der eigenen Idenditaet aus !

Ciao ...