2011-03-01 87 views
61

我想重寫mouseReleaseEvent與一羣QActions和QMenus的...將參數傳遞給插槽

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

所以我想傳遞的一個參數插槽onStepIncreased(你可以想像他們是1 ,5,10,25,50)。你知道我能做到嗎?

+1

而不是傳遞參數,請考慮分析信號內的sender()。 – 2013-03-07 17:41:12

回答

104

使用QSignalMapper。像這樣:

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

我還記得當Qt沒有QSignalMapper的時候,唯一的解決方法是設置連接到相同插槽的對象的屬性,並使用sender() - > property(...) – 2011-03-02 10:56:50

+0

@Kamil Klimek你不必;你可以編寫你自己的映射器:) – 2011-03-04 20:12:48

+0

如果我的'context'參數將一個目標指向一個沒有接觸到動作的類,那麼如何使用它?因此無論如何,'context'信號映射器將無法訪問這些動作,或者如果我將signalmapper放入同一個類中,那麼對於這些​​連接插槽來說就是錯誤的上下文。 – dhein 2016-06-23 11:20:16

9

QObject::sender()函數返回一個指向已經通知該插槽的對象的指針。你可以用這個來找出哪個動作被觸發了

+0

但操作對象無法從插槽中訪問。 – 2011-03-01 10:31:20

+1

我請求你的赦免?該插槽是QObject的子類的成員,因此它也有一個QObject :: sender()成員。只需調用sender(),你將得到一個指向你的動作的QObject *。之後,您可以使用獲取操作的objectName()或property()來收集更多信息。你也可以將它轉換爲一個動作對象,如果你真的想,但我不會建議。 – Septagram 2011-03-01 11:28:29

1

也許你可以用一個m_increase成員變量繼承QAction。
將triggered()信號連接到新QAction子類上的一個插槽,並使用正確的參數發出新信號(例如觸發(int數))。
例如

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

有了Qt 5和C++ 11編譯器,慣用的方式做這樣的事情是,得到仿函數到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); }); 

的第三個參數connect名義上是可選的。它用於設置函數將執行的線程上下文。當仿函數使用QObject實例時,它總是有必要的。如果仿函數使用多個QObject實例,則它們應該有一些管理它們的生命週期的公共父代,並且仿函數應該引用該父代,或者應該確保這些對象將超過仿函數。

在Windows上,這在MSVC2012 &更新。

+5

C++ 11 lambda和Qt 5將函子連接到信號的能力的這種組合是如此有用但尚未被低估的特性。 – Carlton 2016-09-15 14:52:50

+0

我將這個解決方案適用於我的案例。但是,如果我使用'SIGNAL(觸發(布爾))'而不是'&QAction :: triggered',則會引發錯誤。有人可以向我解釋爲什麼? – Deniz 2016-10-01 20:42:46

+0

它不會「拋出」一個錯誤。編譯器會抱怨,錯誤消息應該告訴你爲什麼:沒有'QObject :: connect'重載,它將第二個參數和第三個或第四個參數作爲一個函子。 Qt4風格的'connect'語法不會與新語法混合使用。如果你想使用舊的語法,你會放棄連接到仿函數的容易程度(儘管如果你有一個C++ 11編譯器但是使用了Qt 4,它可以近似)。 – 2016-10-02 14:25:21

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