QCompleter ::在失去并获得焦点后激活断开

时间:2017-11-03 18:47:52

标签: c++ qt qt5

我发现了一个我不明白的奇怪案例。也许这是一个Qt错误,也许我做错了。

标题:

// File mylineedit.h
#pragma once

#include <QLineEdit>
#include <QDebug>

class MyLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit MyLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) { }

public slots:
    void onCompleterActivated(const QString& text) { qDebug() << "MyLineEdit" << text; }
};

主要的源文件:

// File main.cpp
#include <QApplication>
#include <QWidget>
#include <QStringListModel>
#include <QCompleter>
#include <QVBoxLayout>
#include "mylineedit.h"


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    QLineEdit* lineEdit1 = new MyLineEdit();
    QLineEdit* lineEdit2 = new MyLineEdit();

    auto layout = new QVBoxLayout(&w);
    layout->addWidget(lineEdit1);
    layout->addWidget(lineEdit2);

    lineEdit1->setCompleter(new QCompleter());
    auto model = new QStringListModel(QStringList() << "A" << "B" << "C");
    lineEdit1->completer()->setModel(model);
    QObject::connect(lineEdit1->completer(), SIGNAL(activated(QString)), lineEdit1, SLOT(onCompleterActivated(QString)));

    w.show();

    return a.exec();
}

一旦你运行了这个,你可以得到一个完整的价值观&#34; A&#34;,&#34; B&#34;,&#34; C&#34;在第一行编辑。当您选择任何这些值时,它会将消息打印到控制台。这是对的。但随后将焦点转移到另一行编辑然后再返回。尝试选择&#34; A&#34;,&#34; B&#34;,&#34; C&#34;再次。没有打印出消息,信号/插槽似乎已断开连接。有什么想法吗?

使用Qt 5.9.2。使用MinGW 5.3.0和MSVC 2015进行测试。

1 个答案:

答案 0 :(得分:0)

我稍微修改了你的样本并尝试重现你描述的行为,但我不能:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version: " << QT_VERSION_STR;
  // main application
  QApplication app(argc, argv);
  // setup GUI
  QWidget qWin;
  QVBoxLayout qVBox;
  QLineEdit qEdit1;
  qVBox.addWidget(&qEdit1);
  QCompleter qCompl1;
  QStringListModel qComplModel(QStringList() << "A" << "B" << "C");
  qCompl1.setModel(&qComplModel);
  qEdit1.setCompleter(&qCompl1);
  QLineEdit qEdit2;
  qVBox.addWidget(&qEdit2);
  qWin.setLayout(&qVBox);
  qWin.show();
  // install signal handlers
  QObject::connect(&qCompl1,
    static_cast<void(QCompleter::*)(const QString&)>(
      &QCompleter::activated),
    [](const QString &text)
    {
      qDebug() << "Activated: " << text;
    });
  // run-time loop
  return app.exec();
}

我的样本中存在显着差异:

  1. 我使用的是Qt5风格的信号处理程序(我以前常常使用)。
  2. 我没有new Qt小部件(我在编写最小样本时习惯了)。
  3. 对我而言,很难相信其中一项更改会使您描述的问题不间断。

    我在Windows 10(64位)上使用VS2013,Qt 5.9.2编译和测试:

    snapshot of testQCompleter

    我做了以下互动:

    • 点击qEdit1
    • 键入A,然后点击弹出菜单中的A

    输出:

    Activated:  "A"
    

    我接着说:

    • 点击qEdit2
    • 输入B
    • 点击qEdit1
    • 删除文字,输入B,然后点击弹出式菜单中的B

    输出:

    Activated:  "B"
    

    它的工作方式与预期一致。

    经过一番对话后,我在QLineEdit的源代码中查看了woboq.org:

    有趣的部分在QLineEdit::focusOutEvent

    if (d->control->completer()) {
        QObject::disconnect(d->control->completer(), 0, this, 0);
    }
    

    如果我读得正确,那么QLineEdit(由设置的完成者发出的)的所有信号处理程序都将断开连接。我相信这是观察到的问题的原因。 (因此,它适用于lambdas和其他类的方法。)