1

与 lineEdit 关联的 Qcompleter 在 QNetworkRequest 完成的插槽中不起作用。Qcompleter 消失得很快。每次 lineEdit 中的文本更改请求时都会发送。我尝试了一个没有其他代码的演示,它也发生了。

每次编辑lineEdit中的文本时,都会将包含文本的请求发送到我的服务器。然后我想在Qcompleter中显示回复内容。但提示立即消失。

void MainWindow::onRequestFinished(QNetworkReply* reply){

    QStringList stringList;
    stringList << "test1" <<"test2"<<"test3";
    QCompleter* completer = new QCompleter(stringList,this);
    completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    ui->lineEdit->setCompleter(completer);
    reply->deleteLater();
}

void MainWindow::on_lineEdit_textChanged(const QString &arg1)
{
    QUrl url("http://www.google.com");
    QNetworkRequest request;
    request.setUrl(url);
    manager->get(request);
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow){
...
this->manager = new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onRequestFinished(QNetworkReply*)));
...
}
4

1 回答 1

2

逻辑类似于我的旧答案,其中创建了一个模型,该模型将存储信息,这可以防止您在任何时候创建 QCompleter 避免弹出窗口消失的问题。

#include <QtWidgets>
#include <QtNetwork>

class SuggestModel: public QStandardItemModel
{
    Q_OBJECT
public:
    using QStandardItemModel::QStandardItemModel;
    void search(const QString & text)
    {
        QNetworkRequest request = create_request(text);
        if(m_reply)
            m_reply->abort();
        m_reply = manager.get(request);
        connect(m_reply, &QNetworkReply::finished, this, &SuggestModel::onFinished);
        QEventLoop loop;
        connect(this, &SuggestModel::finished, &loop, &QEventLoop::quit);
        loop.exec();
    }
private Q_SLOTS:
    void onFinished(){
        QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
        QUrl url = reply->url();
        if (reply->error() == QNetworkReply::NoError) {
            QVector<QString> choices;
            QByteArray response(reply->readAll());
            QXmlStreamReader xml(response);
            while (!xml.atEnd()) {
                xml.readNext();
                if (xml.tokenType() == QXmlStreamReader::StartElement)
                    if (xml.name() == "suggestion") {
                        QStringRef str = xml.attributes().value("data");
                        choices << str.toString();
                    }
            }
            clear();
            for(const QString & choice: choices)
                appendRow(new QStandardItem(choice));

        }
        reply->deleteLater();
        Q_EMIT finished();
        m_reply = nullptr;
    }
Q_SIGNALS:
    void finished();
private:
    QNetworkRequest create_request(const QString & text){
        const QString suggestUrl(QStringLiteral("http://google.com/complete/search?output=toolbar&q=%1"));
        QString url = suggestUrl.arg(text);
        return QNetworkRequest(url);
    }
    QNetworkAccessManager manager;
    QNetworkReply *m_reply = nullptr;
};

class SuggestCompleter: public QCompleter{
public:
    SuggestCompleter(QObject *parent=nullptr):
        QCompleter(parent)
    {
        SuggestModel *m_model = new SuggestModel(this);
        setModel(m_model);
        setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    }
    QStringList splitPath(const QString &path) const override{
        if(SuggestModel * m = qobject_cast<SuggestModel *>(model()))
            m->search(path);
        return QCompleter::splitPath(path);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QLineEdit le;
    le.setCompleter(new SuggestCompleter(&le));
    le.show();
    return a.exec();
}

#include "main.moc"
于 2019-07-26T05:12:42.080 回答