QT带参数信号的工作原理

4

有人能告诉我带参数的信号是如何工作的吗?我的意思是……如果我声明了一个信号,例如:

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文件,里面有一个pushbutton按钮。当pushbutton被点击后,我想将x1和x3发送到槽函数中。例如:

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

我希望你能清楚一些。非常感谢你的帮助。


问题在于按钮点击信号没有这个签名。https://doc.qt.io/qt-5/qabstractbutton.html#clicked - drescherjm
您可以在Board中设置一个插槽,调用emit clicked(val1, val2),但我不确定您希望如何获取要发出的值。您是否有一个2D按钮数组? - drescherjm
是的,但我不能声明自己的信号吗? - Tojmak
因为这是按钮发出的点击信号的签名。 - drescherjm
那需要发出什么信号呢?我的意思是,我以为我可以重新定义按钮可能发出的信号,我想使用clicked(int, int),并在clicked(bool)的位置提供它。 - Tojmak
显示剩余4条评论
2个回答

4

关于信号/槽的连接规则可以总结为:

你可以忽略信号参数,但不可以从无中创建槽参数

这是什么意思? 如果你的信号有n个参数,则你的槽最多也只能有n个参数(要注意类型)。请看下表。

enter image description here

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

  • 在第二行,你有一个带有一个参数valueChanged(int)的信号。你的槽可以有一个或零个参数(忽略信号参数),但不能有两个或更多参数,因为你不能创建值

  • 在第三行中,信号textChanged(QString)不能与setValue(int)连接,因为我们不能从QString创建一个int值。

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

  • 还要注意的一点是信号/槽的重载。即使用相同名称但参数个数或类型不同的多个信号/槽。例如类QLCDNumber中,槽display有多个重载。在这种情况下,你必须明确地定义哪对信号槽对应,如此处所述。

你可以尝试以下示例:

示例:



#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();
}

4

QObject::connect() 的工作原理如下(一般情况下,不使用 lambda):

connect(obj1, obj1_signal, obj2, ob2_slot)

因为在QPushButton类中没有clicked(int, int)信号(我假设你正在使用该类),所以无法用于连接。

如果你想要在按钮中有clicked(int, int)信号,可以对QPushButton进行子类化,添加信号,并使用emit在处理点击事件的位置发送信号。

然而,这并不是一个好的设计,因为你将不得不在按钮类中存储一个Board对象(或至少是一个对它的引用),这与该类无关。
相反,你可以有一个槽函数Board::buttonClicked(),连接到QPushButton::clicked(bool)。然后在该槽函数中,你可以执行emit Board::clicked(int, int)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接