我们在设计类的信号时也许也会像设计类方法一样,给予多种不同参数类型的重载版本,这样一来我们就可以应对不同类型的参数输入或者输出。
但我们在使用有重载的信号版本时就不那么方便了,QT系统没有那么智能,不会自动匹配,这个时候就可能遇到报错。
一、需求实例
我们以一个具体的例子来看,比如我们现在要给进度条加一个控制,这里用spinbox来控制进度条。我们试图通过spinbox的valuechanged来发送消息给progressbar的代码如下:
ui->progressBar->setRange(0, 100);
ui->spinBox->setRange(0,100);
ui->spinBox->setSingleStep(5);
ui->spinBox->valueChanged(1);
connect(ui->spinBox, &QSpinBox::valueChanged, ui->progressBar, &QProgressBar::setValue);
看起来,上述代码没有问题,一运行,报错来了:
error: no matching function for call to ‘MainWindow::connect(QSpinBox*&, , QProgressBar*&, void (QProgressBar:😗)(int))’
connect(ui->spinBox, &QSpinBox::valueChanged, ui->progressBar, &QProgressBar::setValue);
candidate function not viable: no overload of 'valueChanged' matching 'const char *' for 2nd argument
很显然,那是因为我们的sign中存在两个同名的valueChanged,我们打开spinbox的头文件就可以发现:
很显然,我们为了与progressBar的setValue(int)匹配,这里这里必须明确选择第一个,参数为int的valuechanged。
二、解决方案
1、方案一QOverload
重载调用QOverload::of,利用它来指定多个信号版本中的具体哪种类型参数:
QOverload<参数1类型, 参数2类型,…>::of(&同名的方法名)
修改后代码:
connect(ui->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), ui->progressBar, &QProgressBar::setValue);
完整代码:
ui->progressBar->setRange(0, 100);
ui->spinBox->setRange(0,100);
ui->spinBox->setSingleStep(5);
ui->spinBox->valueChanged(1);
connect(ui->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), ui->progressBar, &QProgressBar::setValue);
2、方案二static_cast
使用static_cast也可以解决,这里的方法比较霸道,不管你是什么类型的参数,这里强制转换为int类型
connect(ui->spinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), ui->progressBar, &QProgressBar::setValue);
三、看看效果
为了使我们的进度条有更丰富的控制效果,我们引入一个自动增长的和一个手动调节的增长效果。
这里的start按钮配合了一个 QTimeLine,具体代码:
QTimeLine *timeLine = new QTimeLine(1000, this);
timeLine->setFrameRange(0, 100);
connect(timeLine, &QTimeLine::frameChanged, ui->progressBar, &QProgressBar::setValue);