2013-01-04 12 views
6

Ich habe ein QMenu mit vielen Untermenüs. Diese werden dynamisch erzeugt, d. H. Die Namensmenüs kommen von einer db und werden in einer Schleife erzeugt. Nun wollte ich den gleichen Slot auslösen() oder ähnliches, wenn ein Menü angeklickt wurde, aber ich brauchte den QString Menünamen, der an Slot übergeben wurde, damit ich menüspezifische Aktionen ausführen konnte. Ich habe versucht this, d. H. Eine QAction * an das ausgelöste Ereignis übergeben und setData verwendet, aber ich bekomme den Laufzeitfehler.Wie man einen QString an einen Qt-Slot von einem QMenu über QSignalMapper oder sonstwie weitergibt

Objekt :: connect: Kein QAction solches Signal :: ausgelöst (QAction *)

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
     QAction *subMenuAct = subMenu->addAction(tr(c_name)); // c_name the menu name 
     subMenuAct->setData(ch_name); 
     connect(subMenuAct, SIGNAL(triggered(QAction *)), this, SLOT(playChannel(QAction *))); // playChannel is the slot 
} 

void <ClassName>::playChannel(QAction *channelAction) 
{ 
    QString str = channelAction->data().toString(); 
    qDebug() << "Selected - " << str; 
} 

Alternativ habe ich auch versucht, QSignalMapper wo signalMapper ein Datenelement im Konstruktor initialisiert ist

signalMapper = new QSignalMapper(this); 

und

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
     QAction *subMenuAct = subMenu->addAction(tr(c_name)); 

     connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map())); 
     signalMapper->setMapping(subMenu, ch_name); 
     connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString))); 
} 

Im zweiten Fall bekomme ich keinen Fehler, jedoch wird die Slot-Funktion playChannel nicht aufgerufen. Würde mich wirklich freuen, wenn jemand helfen könnte, es zu lösen.

Update 1: Der einzige Unterschied, den ich von anderen Beispielen sehe ich gesehen habe, ist, dass Menschen in der Regel Verbindungssignale von mehreren Widgets zu einem einzigen Slot (sagen verschiedene Tasten) sind. In meinem Fall verbinde ich mehrere Untermenüs (mit unterschiedlichen Namen) zu einem einzelnen Steckplatz. Sollte dies einen Unterschied machen?

Update 2: Es funktionierte nach der vorgeschlagenen Korrektur in der Lösung below für QSignalMapper. Auch die Tatsache, dass ich SubMenu als Argument für setMapping verwendete, wo stattdessen das MenuAction-Element verwendet werden sollte. Aber jetzt erhalte ich ein Ereignis, das mehrmals ausgelöst wird, d.h. so oft wie es Einträge im Hauptmenü für die ausgewählte Untermenü-Kategorie gibt. Wenn der Kanaltyp Englisch (Hauptmenü) mit vier Einträgen ist, HBO, Sternfilme usw. (Untermenü) und ich HBO wähle, wird das Ereignis viermal mit der Zeichenfolge HBO ausgelöst. Es funktioniert gut, wenn ich einen separaten Signal-Mapper für jedes Untermenü erstellen. Aber ich hatte gehofft, dass ein einzelner Mapper verwendet werden sollte und ich hier etwas falsch mache. Einige weitere Details in den Kommentaren zur Antwort.

+0

Sie müssen problematischen Code eingrenzen und minimalen Code Beispiel post, die das Problem reproduzieren.Abgesehen davon, dass Sie signalMapper nicht in jeder Iteration mit einem Slot verbinden müssen, sieht alles gut aus. Sind Sie sicher, dass Sie die Slot-Signatur geändert haben? –

+0

Vielen Dank - das sind zwei separate Code-Samples, die das Problem reproduzieren. Ich sehe keinen Weg, es einzugrenzen. Man versucht via Signalmapper wo auch die andere QAction * verwendet. Erste zeigt Laufzeitfehler und die zweite überhaupt nicht, aber keine funktioniert. Und ja, ich bin sicher, dass die Slot-Signatur für jeden von ihnen geändert wurde, d. H. QString in einem Fall und QAction * in dem anderen. Wenn das nicht der Fall ist, erhalte ich einen Kompilierungsfehler. – fayyazkl

+0

In Bezug auf die Verbindung signalMapper in jeder Iteration, wie würde ich angeben, dass jede Iteration von ch_name einen anderen Namen hat und sollte das gleiche erzeugen, wenn aus dem Menü ausgewählt? – fayyazkl

Antwort

5

Nachdem Sie das Menü QAction hinzugefügt haben, müssen Sie nur QMenu an den Steckplatz anschließen. Sie verbinden nicht jede Aktion einzeln an den Schlitz:

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
    ch_name = <name from the database for the channel j>; 
    QAction *subMenuAct = subMenu->addAction(tr(ch_name)); 
    subMenuAct->setData(ch_name); 
} 

connect(subMenu, SIGNAL(triggered(QAction *)), 
     this, SLOT(playChannel(QAction *)), Qt::UniqueConnection); 

Wie ich weiß nicht, wie Sie, wenn Sie subMenu jedes Mal das dynamische Menü gefüllt löschen ist, die Qt::UniqueConnection sicherzustellen, dass der Schlitz nicht wieder angeschlossen werden mehrmals.


Für die Signal-Mapper-Version sollten Sie die Aktionen nur mit dem Mapper in der Schleife verbinden. Die Verbindung vom Mapper zum Slot sollte nur einmal durchgeführt werden.

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
    ch_name = <name from the database for the channel j>; 
    QAction *subMenuAct = subMenu->addAction(tr(ch_name)); 
    connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map())); 
    signalMapper->setMapping(subMenuAct, ch_name); 
} 
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString))); 

Und für diesen Fall sollte der Schlitz playChannel eine QString anstelle eines QAction* akzeptieren.

+0

Danke - Ein Fehler meinerseits war signalMapper-> setMapping (subMenu, ch_name); d. h., ich kartierte auf subMenu, nicht auf subMenuAct. Rest funktioniert, aber jetzt war das Problem, dass das Signal vier Mal gegen einen einzigen Klick aufgerufen wird. Um es klar zu sagen, ich habe eine äußere Schleife, die das Hauptmenü erstellt. Die oben angegebene Schleife ist die innere Schleife mit Untermenüs. Für eine Auswahl von Untermenüs sollte das Ereignis einmal ausgelöst werden, aber es wird so oft aufgerufen, wie es Einträge für dieses Untermenü in der Hauptsache gibt. – fayyazkl

+0

Sagen Sie, wenn der englische Kanal vier verschiedene Kanalnamen hat, und ich wählte "HBO", ruft er HBO viermal statt eins an. Momentan ist es gelöst, wenn ich mehrere Signal-Mapper erstellt habe, wobei jeder Mapper in der Submenü-Schleife erstellt wurde, aber ich denke nicht, dass dies der richtige Weg ist. Würde mich freuen, wenn es behoben werden kann – fayyazkl

+0

@fayyazkl Sie sollten den letzten Verbindungsaufruf außerhalb einer Schleife verschieben und/oder 'Qt :: UniqueConnection' zum Verbindungsaufruf hinzufügen, um mehrere Verbindungen des gleichen Signals zum selben Steckplatz zu vermeiden (falls eine Verbindung besteht wird N mal gemacht, ein Trigger des Signals wird den Slot N mal aufrufen). – alexisdm