Qt-QLineEdit信号editingFinished ()在回车时多次触发的原因以及解决方案?
1. 前言
这是我开发过程中遇到关于QLineEdit的一个小问题,当时比较懵逼,所以记录下,通过阅读,你可能会知道为什么QLineEdit的editingFinished 在回车并弹窗时被触发了两次以及解决方案。
2. 直奔主题
2.1 问题产生的情景
使用QLineEdit获取用户的输入,当检测到用户输入为空时进行弹窗提示,并将QLineEdit重置为默认值,代码如下:
// 连接信号与槽:on_ui对象名称_信号()
void MainWindow::on_lineEdit_editingFinished()
{
// 检测是否为空 其中trimmed()将去掉字符头部和尾部的'\t', '\n', '\v', '\f', '\r', and ' '
if(ui->lineEdit->text().trimmed().isEmpty()){
QMessageBox::warning(this, "Warning", "Invalid data!!");
// 重置
ui->lineEdit->setText("Meoeoeo");
}
}
在界面删除掉输入框所有的字符回车后出现这种情况(连续弹了两个警告框):
2.2 原因分析
(由于我没有去看QLineEdit的实现源码,以下分析仅为个人理解)出现两次弹窗,说明该信号(editingFinished)被emit了两次,分析我们上面的操作,可能会发出信号的地方有两个:
(1)回车时触发
验证:
我们修改代码如下:
void MainWindow::on_lineEdit_editingFinished()
{
qDebug() << "just press enter";
}
输入时直接按回车:
说明回车触发了一次。
(2)弹窗时QLineEdit失去焦点时触发
我们修改代码如下(即不弹窗):
void MainWindow::on_lineEdit_editingFinished()
{
qDebug() << "coming bro!!";
if(ui->lineEdit->text().trimmed().isEmpty()){
ui->lineEdit->setText("Meoeoeo");
}
}
删除完字符后点击回车效果(只有一次输出,说明只是进入了一次即不弹窗未失去焦点仅有一次):
也就是说按照我们之前的写法,回车时触发了信号进了弹窗,然后弹窗时又失去焦点则再次弹窗(此时第一次弹窗还没有被关闭)。
2.3 解决策略
【方案一】
如果仅仅是想解决我背景说到的场景其实很容易,就是将重置QLineEdit的语句放到弹窗前,也就是在弹窗失去焦点前改变处理的条件,代码如下:
void MainWindow::on_lineEdit_editingFinished()
{
qDebug() << "coming bro!!";
if(ui->lineEdit->text().trimmed().isEmpty()){
// 知道为空后就重置为默认值,就算该槽被再次调用,也不会进入该处理逻辑了
ui->lineEdit->setText("Meoeoeo");
QMessageBox::warning(this, "Warning", "Invalid data!!");
}
}
效果如下:
即使该槽还是被触发了两次,但是由于弹窗的条件被修改了,所以只有第一次进行了弹窗,符合我们背景所述的需求。
【方案二(概述)】
其实我们可以分类,QLineEdi的editingFinished 被触发有两种,一种就是有焦点时被触发(比如回车),另一种就是失去焦点时被触发(比如将焦点移除或者弹窗),此处只是提供一种思路,跳开我们的背景,可行的代码如下(概述):
void MainWindow::on_lineEdit_editingFinished()
{
if(ui->lineEdit->hasFocus()) return;
qDebug() << "handle while have no focus!!";
}
void MainWindow::on_lineEdit_returnPressed()
{
qDebug() << "handle while press enter!!";
}
【方案三】
重写QLineEdit,可能大家不想这么办!
3.最后
祝福安好!