Qt:将信号/绑定参数适应插槽?
Posted
技术标签:
【中文标题】Qt:将信号/绑定参数适应插槽?【英文标题】:Qt: adapting signals / binding arguments to slots? 【发布时间】:2009-05-07 17:11:03 【问题描述】:有没有办法将参数绑定到插槽ala boost::bind?
这是一个例子。我有一个带有树视图的窗口,我想允许用户从上下文菜单中隐藏一列。我最终会做类似的事情:
void MyWindow::contextMenuEvent (QContextMenuEvent* event)
m_column = view->columnAt (event->x());
QMenu menu;
menu.addAction (tr ("Hide Column"), this, SLOT (hideColumn ()));
// .. run the menu, etc
我需要捕获激活上下文菜单的列的索引,并将其存储在我窗口的hideColumn
插槽使用的成员变量中:
void MyWindow::hideColumn ()
view->setColumnHidden (m_column, true);
我真正想要的是能够在创建菜单时将列号绑定到我的插槽,这样我就不需要这个成员变量了。基本上相当于 Qt:
menu.addAction (tr ("Hide Column"),
boost::bind (&MyWindow::hideColumn, this,
event->columnAt (event->x()));
或者更好的是调整QAction::triggered 信号并将其附加到QTreeView::hideColumn 插槽,该插槽将列索引作为参数:
menu.addAction (tr ("Hide Column"),
boost::bind (&QTreeView::hideColumn, view,
event->columnAt (event->x())));
这些都可行吗?
【问题讨论】:
现在 Qt 5 支持 C++0x lambda,所有这些混乱都可以处理掉。见qt-project.org/doc/qt-5.0/qtcore/qobject.html#connect-5 【参考方案1】:LibQxt 通过 QxtBoundFunction 和 QxtMetaObject 使这成为可能(由于某种原因,前者没有出现在他们的documentation 中)。这是一个开源项目,因此如果您对实现感兴趣,可以获取源代码。它使用以下语法:
connect(
button,
SIGNAL(clicked()),
QxtMetaObject::bind(
lineEdit,
SLOT(setText(QString)),
Q_ARG(QString, "Hello World!)
)
);
LibQxt 还有一些其他非常有用的功能,比如emit signals over a QIODevice 的功能,比如网络连接。
【讨论】:
【参考方案2】:你不能使用QAction
的setData
函数吗?
void MyWindow::contextMenuEvent (QContextMenuEvent* event)
m_column = view->columnAt (event->x());
QMenu menu;
QAction * action = menu.addAction (tr ("Hide Column"), this, SLOT (hideColumn ()));
action->setData(QVariant(hideColumn));
void hideColumn()
const QAction * action = qobject_cast<const QAction *>(this->sender());
assert(action);
int hide_column = action->data().value<int>();
this->view->setColumnHidden (m_column, true);
【讨论】:
不错。不知道setData。既然可以在 Qt 5 中使用 C++0x lambda,那么这种混乱就可以完全消失了。耶!【参考方案3】:AFAIK 唯一的方法是创建一个 QSignalMapper 对象来执行此操作。这就像一个额外的间接级别,可用于生成提供列索引的新信号。这有点笨拙的 IME,你可能会一直挂着很多 QSignalMapper 对象,但这似乎是目前最好的方式。 (理想情况下,IMO,您可以只提供任何值,例如将列索引作为 connect() 的参数传递给插槽,但您不能。)
【讨论】:
是的。 QT 信号非常低级(至少在当前版本中,在遥远的将来可能会有希望;)。实际上它们是基于文本的(只需查看 moc_xx.cpp 文件或如何定义 SLOT/SIGNAL 宏。)【参考方案4】:正如上面评论中提到的,这在 Qt 5 中要容易得多,因为您可以将信号直接连接到函子,例如 std::tr1::bind() 或 boost::bind() 的结果。对于 Qt 4,有许多适配器库。 Kaleb 提到了 LibQxt。我有一个https://github.com/robertknight/qt-signal-tools
【讨论】:
以上是关于Qt:将信号/绑定参数适应插槽?的主要内容,如果未能解决你的问题,请参考以下文章