Qt 将参数传递给插槽

Qt 将参数传递给插槽,qt,qsignalmapper,qt-slot,Qt,Qsignalmapper,Qt Slot,我想用一堆Qaction和QMenus覆盖mouseReleaseEvent connect(action1, SIGNAL(triggered()), this, SLOT(onStepIncreased())); connect(action5, SIGNAL(triggered()), this, SLOT(onStepIncreased())); connect(action10, SIGNAL(triggered()), this, SLOT(onStepIncreased()))

我想用一堆Qaction和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()));
因此,我想将一个参数传递到slot
onsteppereduced
(可以想象它们是1,5,10,25,50)。你知道我怎么做吗?

该函数返回一个指向已向插槽发出信号的对象的指针。您可以使用它来找出触发了哪个操作。像这样:

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

也许您可以使用m_increase成员变量将QAction子类化。
将triggered()信号连接到新QAction子类上的插槽,并使用正确的参数发出新信号(例如triggered(int number))。
e、 g


使用Qt5和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
实例时,它总是必需的。如果functor使用多个
QObject
实例,则它们应该有一些管理其生存期的公共父对象,并且functor应该引用该父对象,或者应该确保对象比functor更长寿

在Windows上,这适用于MSVC2012及更新版本。

QVector W(100);
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)));
} 
W[1]=动作1; W[5]=动作5; W[10]=行动10; W[25]=行动25; W[50]=行动50; 对于(int i=0;isetMapping(W[i],i); 连接(信号映射器,信号映射器(int)),此,插槽(onsteppereduced(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)
;在每次worker发出错误信号时调用

userErrorslot
每次连接到客户端的套接字遇到错误时都会执行。它具有以下签名:

void ChatServer::userError(ServerWorker *sender)
{
    //some code
}

请原谅?该插槽是QObject子类的成员,因此它还有一个QObject::sender()成员。只需调用sender(),您将获得一个指向您的操作的QObject*。之后,您可以使用objectName()或property()收集更多信息的已获取操作。如果确实需要,您也可以将其转换为操作对象,但我不建议这样做。我仍然记得,Qt没有QSignalMapper,唯一的解决方案是在连接到同一插槽的对象上设置属性,并使用sender()->property(…)@Kamil Klimek您不必这样做;您可以编写自己的映射程序:)如果我的
上下文
参数将一个对象指向一个无法访问操作的类,那么如何使用它?因此,
context
signalmapper将无法访问操作,或者如果我将signalmapper放入同一个类,则连接槽的上下文将是错误的。值得注意的是(2018年,Qt5,C++11),QSignalMapper已被弃用。从这个链接中可以看出:“这个类是过时的。它是为了保持旧的源代码工作。我们强烈建议不要在新代码中使用它。”下面的“KuBA”的答案现在是更好的。代替传递参数,考虑分析SENDE()。在信号内部。C++11 lambdas和Qt 5将函子连接到信号的能力的结合是非常有用的,但被低估了。我根据我的情况调整了这个解决方案。但是,如果我使用
信号(triggered(bool))
而不是
&QAction::triggered
,它会抛出一个错误。谁能给我解释一下为什么?它不会“抛出”错误。编译器会抱怨,错误消息应该告诉您原因:没有
QObject::connect
重载将
const char*
作为第二个参数,将函子作为第三个或第四个参数。Qt4样式
connect
语法与新语法不兼容。如果您希望使用旧语法,那么您将失去连接到函子的便利性(即使如果您使用的是C++11编译器,但使用的是Qt4,也可能是近似的)。
void ChatServer::userError(ServerWorker *sender)
{
    //some code
}