Passing an argument to a slot
I want to override mouseReleaseEvent with a bunch of QAc开发者_Go百科tions and 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()));
So I want to pass an argument to the slot onStepIncreased
(as you can imagine they are 1,5,10,25,50). Do you know how I can do it?
With Qt 5 and a C++11 compiler, the idiomatic way to do such things is to give a functor to 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); });
The third argument to connect
is nominally optional. It is used to set up the thread context in which the functor will execute. It is always necessary when the functor uses a QObject
instance. If the functor uses multiple QObject
instances, they should have some common parent that manages their lifetime and the functor should refer to that parent, or it should be ensured that the objects will outlive the functor.
On Windows, this works in MSVC2012 & newer.
Use QSignalMapper. Like this:
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))) ;
The QObject::sender()
function returns a pointer to the object that has signaled to the slot. You could use this to find out which action was triggered
Maybe you can subclass QAction with an m_increase member variable.
Connect the triggered() signal to a slot on your new QAction subclass and emit a new signal (e.g. triggered(int number)) with the correct parameter.
e.g.
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;
};
You can use std::bind
This is a functional object adapter that allows functional objects to be adaptee to a given number of parameters.
For example, you create your own chat server. That contains two classes: ChatServer and ServerWorker.
ChatServer is QTcpServer class and ServerWorker is QTcpSocket ( manage the socket on the server side).
Signals in ServerWorker header:
void error();
In your ChatServer header you define these private slots:
void userError(ServerWorker *sender);
In cpp file you create these object and in incomingConnection
method that run after socket connect, you connect slots and signals using std::bind
:
void ChatServer::incomingConnection(qintptr socketDescriptor)
{
//some code
connect(worker, &ServerWorker::error, this, std::bind(&ChatServer::userError, this, worker));
}
std::bind
creates a functor with some fixed arguments. For example connect(worker, &ServerWorker::error, this, std::bind(&ChatServer::userError, this, worker));
will result in this->userError(worker)
; to be called every time the worker emits the error signal.
userErrorslot
is executed every time a socket connected to a client encounters an error. It has signature:
void ChatServer::userError(ServerWorker *sender)
{
//some code
}
Example
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)));
}
精彩评论