带参数的 QT 信号如何工作

How QT signals with parameters works

谁能告诉我带参数的信号究竟是如何工作的?我的意思是...如果我声明了信号 f.e.:

void sign1(int)

我应该如何指定我想用那个信号发送什么整数?另外,我可以用多个参数声明信号吗?喜欢:

void sign2(int, int)

再一次...我想用 sign2 发送我拥有的四个变量中的两个。这可能吗,应该怎么做?下面是一个更详细的例子来说明我的问题:

class Board
{
  signals: 
    void clicked(int, int);
  private:
    int x1{4}; int x2{4}; int x3{5}; int x4{8};
}

并且有 board.ui 个带按钮的文件。单击按钮后,我想发送到插槽,例如 x1 和 x3。示例:

connect(ui->button, SIGNAL(clicked(int, int)), obj2, slot2); 

我希望它能以某种方式清楚。非常感谢您的帮助。

QObject::connect() 像这样工作(在一般情况下,不使用 lambda):

connect(obj1, obj1_signal, obj2, ob2_slot)

由于 class QPushButton 中没有信号 clicked(int, int) (我假设您正在使用),因此无法用于连接。

如果你想在一个按钮中有信号clicked(int, int),你可以subclass QPushButton,添加信号,并使用emit发送信号处理点击事件的地方。

但是,这不是一个好的设计,因为您必须在按钮 class 中存储一个 Board 对象(或至少是对它的引用),这与 class.
相反,您可以有一个插槽 Board::buttonClicked(),连接到 QPushButton::clicked(bool)。然后在那个插槽中,你可以做 emit Board::clicked(int, int).

signal/slot连接的规则可以表述如下:

You can ignore signal arguments, and you cannot create slot arguments from nothing

这是什么意思? 如果你的信号有一个参数,你的插槽最多也应该有一个参数。见下表。

  • 在第一行,你有一个带有两个参数的信号,因此,你的插槽可以有两个参数(使用所有信号参数),或一个参数(忽略信号的一个参数)或无参数(忽略两个信号参数)

  • 在第二行,您有一个带有一个参数的信号 valueChanged(int)。您的插槽可能有一个参数或没有参数(忽略信号参数)但 可能不会 有两个 或更多参数 you cannot create values.

  • 在第三行,信号 textChanged(QString) 无法与 setValue(int) 连接,因为我们无法从 QString 创建 int 值。

  • 第四行遵循这些规则。如果信号没有参数,连接的信号不能创建新参数,因此 update() 是正确的,setValue(int) 不是。

  • 另一个需要注意的点是 signal/slot 的重载。在这种情况下,许多 signals/slots 具有相同的名称但具有不同的数字或不同类型的参数。 您可能有 class QLCDNumber,其中插槽 display 有很多过载。在此 cas 中,您必须明确定义要按说明使用的信号槽对 here

您可以试试下面的例子:

示例:



#include <QtWidgets>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget *window = new QWidget();
    window->setAttribute(Qt::WA_DeleteOnClose);
    QVBoxLayout *topLayout = new QVBoxLayout(window);

    //Set up of GUI
    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 100);

    QSpinBox *spin = new QSpinBox;
    spin->setReadOnly( true );

    QHBoxLayout *horizontalLayout = new QHBoxLayout;
    horizontalLayout->addWidget(slider);
    horizontalLayout->addWidget(spin);
    topLayout->addLayout(horizontalLayout);

    // using pointer to member function
    QObject::connect(slider, &QSlider::valueChanged,
                     spin, &QSpinBox::setValue);
    // set the slider position and hence the QSpinBox value too
    slider->setValue(40);

    // Uncommenting the following connect will result in a compile time error.
    // The signal passes no arguments whereas the slot is expecting a single
    // argument.
    // By using function pointers we get compile time parameter list checking.
    // Using the old-style SIGNAL/SLOT macros this would have been detected
    // as a run time warning only.
    //QObject::connect(slider, &QSlider::sliderPressed,
    //                 spin, &QSpinBox::setValue);

    QTextEdit *textEdit = new QTextEdit();
    textEdit->setAttribute(Qt::WA_DeleteOnClose);

    // Uncommenting the following connect will result in a compile time error.
    // The signal is passing an incompatible parameter to the slot.
    // By using function pointers we get compile time parameter type conversion.
    // Using the old-style SIGNAL/SLOT macros this would have been detected
    // as a run time warning only.
    //QObject::connect(slider, &QSlider::sliderMoved,
    //                 textEdit, &QTextEdit::setFontFamily);

    window->show();
    return app.exec();
}