我想用一堆 QActions 和 QMenus 覆盖 mouseReleaseEvent ......
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)。你知道我该怎么做吗?
使用 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 及更高版本。
使用 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))) ;
context
参数将 a 定位到无法访问操作的类,如何使用它?所以无论如何,context
信号映射器将无法访问这些操作,或者如果我将信号映射器放入同一个类中,那么连接槽的上下文将是错误的。
QObject::sender()
函数返回一个指向已向插槽发出信号的对象的指针。您可以使用它来找出触发了哪个操作
也许您可以使用 m_increase 成员变量对 QAction 进行子类化。将trigger() 信号连接到新QAction 子类上的插槽并发出具有正确参数的新信号(例如trigger(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)));
}
您可以使用 std::bind
这是一个功能对象适配器,它允许功能对象适应给定数量的参数。
例如,您创建自己的聊天服务器。它包含两个类:ChatServer 和 ServerWorker。
ChatServer 是 QTcpServer 类,ServerWorker 是 QTcpSocket(管理服务器端的套接字)。
ServerWorker 标头中的信号:
void error();
在您的 ChatServer 标头中,您定义了这些私有插槽:
void userError(ServerWorker *sender);
在 cpp 文件中创建这些对象,并在套接字连接后运行的 incomingConnection
方法中,使用 std::bind
连接插槽和信号:
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
}
SIGNAL(triggered(bool))
而不是&QAction::triggered
,则会引发错误。有人可以向我解释为什么吗?QObject::connect
重载将const char *
作为第二个参数,将仿函数作为第三个或第四个参数。 Qt4 风格的connect
语法不与新语法混合。如果您希望使用旧语法,那么您将失去连接仿函数的便利性(即使如果您有 C++11 编译器但使用 Qt 4,它也可以近似)。