Передача аргумента в слот
Я хочу переопределить 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). Ты знаешь, как я могу это сделать?
6 ответов
Используйте 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))) ;
С 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 и новее.
QObject::sender()
Функция возвращает указатель на объект, который подал сигнал в слот. Вы можете использовать это, чтобы узнать, какое действие было вызвано
Вы можете использовать Это адаптер функциональных объектов, который позволяет адаптировать функциональные объекты к заданному количеству параметров.
Например, вы создаете свой собственный чат-сервер. Он содержит два класса: ChatServer и ServerWorker.
ChatServer - это класс QTcpServer, а ServerWorker - это QTcpSocket (управление сокетом на стороне сервера).
Сигналы в заголовке ServerWorker:
void error();
В заголовке ChatServer вы определяете эти частные слоты:
void userError(ServerWorker *sender);
В файле cpp вы создаете этот объект, а в
incomingConnection
метод, который запускается после подключения сокета, вы подключаете слоты и сигналы, используя:
void ChatServer::incomingConnection(qintptr socketDescriptor)
{
//some code
connect(worker, &ServerWorker::error, this, std::bind(&ChatServer::userError, this, worker));
}
std::bind
создает функтор с некоторыми фиксированными аргументами. Например
connect(worker, &ServerWorker::error, this, std::bind(&ChatServer::userError, this, worker));
приведет к
this->userError(worker)
; вызывается каждый раз, когда рабочий выдает сигнал об ошибке.
userErrorslot
выполняется каждый раз, когда сокет, подключенный к клиенту, обнаруживает ошибку. Имеется подпись:
void ChatServer::userError(ServerWorker *sender)
{
//some code
}
Возможно, вы можете создать подкласс QAction с помощью переменной-члена m_increase.
Подключите сигнал triggered() к слоту вашего нового подкласса QAction и подайте новый сигнал (например, triggered(int number)) с правильным параметром.
например
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;
};
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)));
}