2011-03-01 20 views
61

Quiero anular mouseReleaseEvent con un montón de QActions y QMenus ...Al pasar un argumento a una ranura

connect(action1, SIGNAL(triggered()), this, SLOT(onStepIncreased())); 

connect(action5, SIGNAL(triggered()), this, SLOT(onStepIncreased())); 

connect(action10, SIGNAL(triggered()), this, SLOT(onStepIncreased())); 

connect(action25, SIGNAL(triggered()), this, SLOT(onStepIncreased())); 

connect(action50, SIGNAL(triggered()), this, SLOT(onStepIncreased())); 

así que quiero pasar un argumento a la ranura onStepIncreased (como se puede imaginar que son 1 , 5,10,25,50). ¿Sabes cómo puedo hacerlo?

+1

En lugar de pasar parámetros, considere analizar el remitente() dentro de la señal. –

Respuesta

104

Use QSignalMapper. De esta manera:

QSignalMapper* signalMapper = new QSignalMapper (this) ; 
connect (action1, SIGNAL(triggered()), signalMapper, SLOT(map())) ; 
connect (action5, SIGNAL(triggered()), signalMapper, SLOT(map())) ; 
connect (action10, SIGNAL(triggered()), signalMapper, SLOT(map())) ; 
connect (action25, SIGNAL(triggered()), signalMapper, SLOT(map())) ; 
connect (action50, SIGNAL(triggered()), signalMapper, SLOT(map())) ; 

signalMapper -> setMapping (action1, 1) ; 
signalMapper -> setMapping (action5, 5) ; 
signalMapper -> setMapping (action10, 10) ; 
signalMapper -> setMapping (action25, 25) ; 
signalMapper -> setMapping (action50, 50) ; 

connect (signalMapper, SIGNAL(mapped(int)), this, SLOT(onStepIncreased(int))) ; 
+0

Aún recuerdo momentos en que Qt no tenía QSignalMapper, y la única solución era establecer propiedades en objetos conectados a la misma ranura y usar remitente() -> propiedad (...) –

+0

@Kamil Klimek No era necesario ; podrías haber escrito tu propio mapeador :) –

+0

¿Cómo usar esto si mi parámetro 'context' se dirige a una clase que no tiene acceso a las acciones? de todos modos, el señalizador de contexto 'context' no tendría acceso a las acciones, o si tuviera el mapeador de señal en la misma clase, sería el contexto incorrecto para las ranuras de conexión. – dhein

9

La función QObject::sender() devuelve un puntero al objeto que se ha señalizado en la ranura. Puede usar esto para averiguar qué acción se activó

+0

pero los objetos de acción son inaccesibles desde la ranura .. –

+1

¿Perdón? El slot es miembro de una subclase de QObject, por lo que también tiene un miembro QObject :: sender(). Simplemente llame al remitente(), y se le dará un QObject * que le indicará su acción. Después de eso, puede usar objectName() o property() de una acción adquirida para recopilar más información. También puede convertirlo en un objeto de acción si realmente lo desea, pero no lo recomendaría. – Septagram

1

Tal vez pueda la subclase QAction con una variable de miembro m_increase.
Conecte la señal disparada() a una ranura en su nueva subclase QAction y emita una nueva señal (por ejemplo, desencadenada (número int)) con el parámetro correcto.
p.

class MyAction:public QAction 
{ 
public: 
    MyAction(int increase, ...) 
     :QAction(...), m_increase(increase) 
    { 
     connect(this, SIGNAL(triggered()), this, SLOT(onTriggered())); 
    } 
protected Q_SLOTS: 
    void onTriggered() 
    { 
     emit triggered(m_increase); 
    } 

Q_SIGNALS: 
    void triggered(int increase); 

private: 
    int m_increase; 
}; 
79

con Qt 5 y un compilador C++ 11, la forma idiomática que hacer este tipo de cosas es dar un funtor a connect:

connect(action1, &QAction::triggered, this, [this]{ onStepIncreased(1); }); 
connect(action5, &QAction::triggered, this, [this]{ onStepIncreased(5); }); 
connect(action10, &QAction::triggered, this, [this]{ onStepIncreased(10); }); 
connect(action25, &QAction::triggered, this, [this]{ onStepIncreased(25); }); 
connect(action50, &QAction::triggered, this, [this]{ onStepIncreased(50); }); 

El tercer argumento a connect es nominalmente opcional. Se usa para configurar el contexto del hilo en el que se ejecutará el funtor. Siempre es necesario cuando el funtor usa una instancia QObject. Si el controlador usa múltiples instancias QObject, deberían tener algún elemento principal común que administre su tiempo de vida y el programa de ejecución debería referirse a ese elemento primario, o se debería garantizar que los objetos sobrevivirán al elemento de ejecución.

En Windows, esto funciona en MSVC2012 & más nuevo.

+5

Esta combinación de C++ 11 lambdas y la capacidad de Qt 5 de conectar un funtor a una señal es una función tan útil y subestimado. – Carlton

+0

Adapte esta solución a mi caso. Sin embargo, arroja un error si uso 'SIGNAL (triggered (bool))' en lugar de '& QAction :: triggered'. ¿Alguien puede explicarme por qué? – Deniz

+0

No "arroja" un error. El compilador se queja, y el mensaje de error debería decirle por qué: no hay una sobrecarga 'QObject :: connect' que tome' const char * 'como el segundo argumento y un functor como tercer o cuarto argumento. La sintaxis 'connect' del estilo Qt4 no se mezcla con la nueva sintaxis. Si desea utilizar la sintaxis anterior, perderá la facilidad de conectarse a los funtores (aunque podría ser aproximado si tuviera un compilador C++ 11 pero utilizara Qt 4). –

0
QVector<QAction*> W(100); 
W[1]= action1; 
W[5]= action5; 
W[10]= action10; 
W[25]= action25; 
W[50]= action50; 

for (int i=0; i<100; ++i) 
{ 
    QSignalMapper* signalmapper = new QSignalMapper(); 
    connect (W[i], SIGNAL(triggered()), signalmapper, SLOT(map())) ; 
    signalmapper ->setMapping (W[i], i); 
    connect (signalmapper , SIGNAL(mapped(int)), this, SLOT(onStepIncreased(int))); 
} 
Cuestiones relacionadas