2013-01-04 11 views
6

Ho un QMenu con molti sottomenu. Questi sono creati dinamicamente, cioè i menu dei nomi provengono da un db e sono creati in un ciclo. Ora volevo attivare lo stesso slot triggerato() o simile quando si fa clic su un menu, ma avevo bisogno che il nome del menu QString passasse allo slot in modo da poter eseguire azioni specifiche del menu. Ho provato this passando un QAction * all'evento innescato e ho usato setData ma sto ottenendo l'errore di run time.Come passare un QString a uno slot Qt da un QMenu tramite QSignalMapper o altrimenti

oggetto :: Connect: Nessun segnale QAction :: innescato (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; 
} 

In alternativa, ho anche provato QSignalMapper dove signalMapper è un membro di dati inizializzata nel costruttore

signalMapper = new QSignalMapper(this); 

e

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))); 
} 

Nel secondo caso, non ho alcun errore, tuttavia la funzione di slot playChannel non viene chiamata. Apprezzeremmo davvero se qualcuno potesse aiutarlo a risolverlo.

Update 1: L'unica differenza che vedo da altri esempi che ho visto è che di solito le persone sono segnali di collegamento da diversi widget ad un singolo slot (dire diversi pulsanti). Nel mio caso sto collegando diversi sottomenu (con nomi diversi) a un singolo slot. Questo dovrebbe fare qualche differenza?

Aggiornamento 2: Ha funzionato dopo la correzione suggerita nella soluzione below per QSignalMapper. Anche il fatto che stavo usando SubMenu come argomento per setMapping, dove invece dovrebbe essere usato come elemento MenuAction. Ma ora sto facendo scattare l'evento più volte, cioè tante volte quante sono le voci nel menu principale per la categoria del sottomenu selezionato. Se il tipo di canale è inglese (menu principale) con quattro voci), HBO, film di stelle ecc. (Sottomenu), e scelgo HBO, quindi l'evento viene attivato quattro volte con stringhe HBO. Funziona bene se creo un separatore di segnali separato per ogni sottomenu. Ma speravo che un singolo mapper dovrebbe essere usato e sto facendo qualcosa di sbagliato qui. Alcuni altri dettagli nei commenti alla risposta.

+0

È necessario limitare il codice problematico e inviare un esempio di codice minimo che riprodurrà il problema.Tranne che non è necessario connettere signalMapper a uno slot in ogni iterazione, tutto sembra a posto. Sei sicuro di aver cambiato la firma dello slot? –

+0

Grazie - questi sono due campioni separati di codice minimo che riproducono il problema in entrambi i modi. Non vedo un modo per restringerlo. Uno cerca tramite signal mapper dove l'altro ha usato QAction *. In primo luogo mostra l'errore di run time e il secondo non lo fa affatto, ma nessuno funziona. E sì, sono sicuro che la firma dello slot è stata cambiata per ognuno di essi, cioè QString in un caso e QAction * nell'altro. Se non è il caso, mi imbatto in errore di compilazione. – fayyazkl

+0

Per quanto riguarda il collegamento signalMapper in ogni iterazione, come dovrei specificare che ogni iterazione di ch_name ha un nome diverso e dovrebbe produrre lo stesso quando selezionato dal menu? – fayyazkl

risposta

5

Dopo aver aggiunto QAction al menu, è sufficiente connettere lo QMenu allo slot. Non si connette ogni azione individuale allo slot:

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); 

Come io non so voi come se si elimina subMenu ogni volta che viene riempito il menu dinamico, il Qt::UniqueConnection assicurarsi che lo slot non sarà ricollegato più volte.


Per la versione del signal mapper, è necessario collegare le azioni al programma di analisi nel ciclo. La connessione dal mapper allo slot dovrebbe essere eseguita solo una volta.

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))); 

E per questo caso, lo slot playChannel dovrebbe accettare un QString invece di un QAction*.

+0

Grazie - Un mio errore è stato signalMapper-> setMapping (sottomenu, ch_name); cioè stavo mappando su subMenu, non su submenuAct. Il riposo funziona, ma ora il problema era che il segnale veniva chiamato quattro volte contro un singolo clic. Per essere chiari, ho un ciclo esterno che crea il menu principale. Il ciclo sopra indicato è il ciclo interno con i sottomenu. Per una selezione di sottomenu, l'evento dovrebbe essere attivato una volta, ma viene chiamato tante volte quante sono le voci per quel sottomenu nel main. – fayyazkl

+0

Supponiamo che il canale inglese abbia quattro diversi nomi di canali e io abbia scelto "HBO", chiama HBO quattro volte, anziché uno. Attualmente, è risolto se ho creato più mappatori di segnali con ogni mapper creato nel lato del ciclo del sottomenu, ma non penso che sia la strada giusta. Gradirei se potesse essere corretto – fayyazkl

+0

@fayyazkl Dovresti spostare l'ultima chiamata di connessione al di fuori di qualsiasi loop e/o aggiungere 'Qt :: UniqueConnection' alla chiamata di connessione per evitare più connessioni dello stesso segnale allo stesso slot (se una connessione viene effettuato N volte, un trigger del segnale chiamerà lo slot N volte). – alexisdm

Problemi correlati