Qt:QLineEdit在更改焦点时两次编辑完成信号?

时间:2014-11-06 14:44:01

标签: c++ qt signals qlineedit slot

我发现了一些类似的问题,但这些问题似乎是指插槽处理程序中使用了消息框的情况。在我的情况下,我有点卡住,因为我得到editFinished信号两次,即使我的插槽处理程序什么都不做。

对于测试,我有一个QLineEdit数组,它使用signalMapper将editingFinished()信号连接到一个插槽。 signalMapper传递数组索引,以便我可以看到信号的来源。 例如:

testenter::testenter(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::testenter)
{
    // setup the UI according to the .h file
    ui->setupUi(this);

    signalMapper = new QSignalMapper(this);

    // init the labels and edit boxes
    for (int i = 0; i < 10; i++)
    {
        pm_label[i] = new QLabel(ui->scrollArea);
        QString text = QString("Number %1").arg(i);
        pm_label[i]->setText(text);
        pm_label[i]->setGeometry(10,20+i*30, 50, 20);
        pm_label[i]->show();

        pm_editBox[i] = new QLineEdit(ui->scrollArea);
        pm_editBox[i]->setGeometry(80,20+i*30, 50, 20);
        pm_editBox[i]->show();

        signalMapper->setMapping(pm_editBox[i], int(i));
        connect(pm_editBox[i], SIGNAL(editingFinished()), signalMapper, SLOT(map()));
    }
    connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(data_entry(int)));
}

void testenter::data_entry(int entry)
{
    //dummy
}

当在调试器中运行时,如果我将数据输入到一个框中,然后点击返回或用鼠标选择另一个框(即更改焦点),然后它调用data_entry两次,第一次使用丢失的框的索引聚焦和第二次使用获得焦点的盒子。

所以我的问题:我错过了什么吗?这是预期的行为还是一个错误? 如果有错误,任何人都知道绕过它的方法,因为我想使用此信号在输入数据时对数据进行自定义验证(通过返回,制表符或鼠标单击来更改焦点)。

3 个答案:

答案 0 :(得分:3)

首先,没有这不是预期的行为,即选择QLineEdit不应该导致它发出editingFinished信号。

有几种可能导致此问题:

  • 您意外将信号两次连接到插槽
  • 广告位map()导致新选择的框失去焦点
  • 同样徒劳无功,如果您正在调试并使用断点来检测插槽被调用的时间,那么当活动应用程序从您的{{{}更改时,可能会导致QLineEdit失去焦点1}}到你的调试器,再次导致信号再次发送。

如果您因为双重连接的插槽而遇到问题,但由于您专门从两个不同的QWidget获取信号,情况似乎并非如此通过指定连接类型可以确保不会发生这种情况,QLineEdit方法实际上在末尾有一个额外的可选参数,允许您将类型从connect更改为{ {1}}。

话虽这么说,数据验证是Qt已经建立的机制,我建议你尽可能使用它,考虑扩展DefaultConnection抽象基类Ref Doc。然后,您告诉每个UniqueConnection使用相同的QValidator

答案 1 :(得分:0)

我遇到了同样的问题。它确实发出两次信号,这是一个已知的错误:https://bugreports.qt.io/browse/QTBUG-40但是很长时间没有得到解决。

最后,我发现在我的情况下,最佳解决方案是将信号从editingFinished更改为returnPressed。作为副作用,从用户的角度来看,这可以更加可预测地发挥作用。另见:http://www.qtforum.org/article/33631/qlineedit-the-signal-editingfinished-is-emitted-twice.html?s=35f85b5f8ea45c828c73b2619f5750ba9c686190#post109943

答案 2 :(得分:0)

OP“对此发现了一些类似的问题,但这些问题似乎是指在插槽处理器中使用消息框的情况。”好吧,这也是我的情况,这就是我的最终结果。因此,冒着失去话题的风险...

在我的情况下,当我的广告位接收到editingFinished发送的QLineEdit信号时,我启动模式QMessageBox向用户询问一些信息。该消息框的出现是触发QLineEdit发送第二个不良editingFinished信号的原因。

@ V.K提到的错误报告(https://bugreports.qt.io/browse/QTBUG-40)中的帖子。提供了对我有帮助的解决方法。以下是我的解决方法的实现。我让Qt magic mojo自动将QLineEdit信号连接到我的MainWindow插槽。

void MainWindow::on_textbox_editingFinished( void )
{
  QLineEdit * pTextbox = qobject_cast<QLineEdit *>( QObject::sender() );
  if ( !pTextbox->isModified() )
  {
    // Ignore undesirable signals.
    return;
  }

  pTextbox->setModified( false );

  // Do something with the text.
  doSomething( pTextbox->text() );
}

void MainWindow::doSomething( QString const & text )
{
  QMessageBox box( this );
  box.setStandardButtons( QMessageBox::Yes | QMessageBox::No );
  box.setText( "Are you sure you want to change that text value?" );
  if ( box.exec() == QMessageBox::Yes )
  {
    // Store the text.
    m_text = text;
  }
}