1

我可以在 Qt 中使用全局插槽吗?

我正在尝试使用此代码,但它似乎不起作用。

slots void f(int i);

void connect(QSpinBox *spinBox)
{
    QObject::connect(spinBox, SIGNAL(valueChanged(int)), NULL, SLOT(f(int)));
}

void f(int i)
{
    // ...
}
4

1 回答 1

2

评论中已经指出:没有全局插槽。


另一方面,从 Qt5 开始,您可以将任何方法连接到信号,即使它没有被标记为插槽。您甚至可以将全局函数和 lambda 表达式连接到信号。因此,如果放弃了对“SLOT”的要求(并且可能被称为“信号处理程序”),它可能会提供您(可能)要求的内容。

示例代码testQSpinBox.cc

// Qt header:
#include <QtWidgets>

// function with matching signature
void f(int value)
{
  qDebug() << value;
}

// function with non-matching signature
void g(const char *text, int value)
{
  qDebug() << text << value;
}

int main(int argc, char **argv)
{
  qDebug() << "Version:" << QT_VERSION_STR;
  // main application
  QApplication app(argc, argv);
  qDebug() << QApplication::style()->objectName();
  // setup GUI
  QWidget qWin;
  QVBoxLayout qBox;
  QSpinBox qSpinBox1;
  qBox.addWidget(&qSpinBox1);
  QSpinBox qSpinBox2;
  qBox.addWidget(&qSpinBox2);
  QSpinBox qSpinBox3;
  qBox.addWidget(&qSpinBox3);
  qWin.setLayout(&qBox);
  qWin.show();
  // install signal handlers
  // connect f() to qSpinBox1::valueChanged
  QObject::connect(&qSpinBox1,
    (void (QSpinBox::*)(int))&QSpinBox::valueChanged,
    &f);
  // connect lambda to qSpinBox2::valueChanged
  QObject::connect(&qSpinBox2,
    (void (QSpinBox::*)(int))&QSpinBox::valueChanged,
    [](int value) { qDebug() << "qSpinBox2:" << value; });
  // use lambda as adapter for function g()
  QObject::connect(&qSpinBox3,
    (void (QSpinBox::*)(int))&QSpinBox::valueChanged,
    [](int value) { g("qSpinBox3:", value); });
  // run application
  return app.exec();
}

为了在cygwin中编译它,我准备了一个 QMake 文件testQSpinBox.pro

SOURCES = testQSpinBox.cc

QT += widgets

使用 g++ 编译和测试:

$ qmake-qt5 testQSpinBox.pro

$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQSpinBox.o testQSpinBox.cc
g++  -o testQSpinBox.exe testQSpinBox.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 

$ ./testQSpinBox 
Version: 5.9.2
"fusion"

testQSpinBox 的快照

(我单击了每个旋转框的向上按钮来强制valueChanged信号。)

1
qSpinBox2: 1
qSpinBox3: 1

笔记:

有一个专业涉及QSpinBox::valueChanged()- 实际上有两个:

void QSpinBox::valueChanged(int i);

void QSpinBox::valueChanged(const QString &text);

因此,如果我们在 中提供信号QObject::connect(),则方法标识符是不明确的。我们必须提供一个“方法指针转换”来解决歧义:

#if 0 // Ambiguity:
QObject::connect(&qSpinBox1, &QSpinBox::valueChanged, &f);
#else // Solve ambinguity:
QObject::connect(&qSpinBox1,
  (void(QSpinBox::*)(int))&QSpinBox::valueChanged,
  &f);
#endif // 0

具有多个签名的信号是 Qt 中的少数例外。通常,连接 Qt 5 风格的信号时,不需要那种丑陋的方法指针转换。


顺便提一句。在我对SO: QPushButton doesn't update when setDown is called的回答中,我编写了支持 Qt 4Qt 5 的代码。因此,对于与现代 Qt 5 信号处理程序相反的老式 Qt SLOT,这可能很有趣。

于 2018-01-22T09:46:17.353 回答