【问题标题】:QtQuick text search autocomplete using google autocomplete使用谷歌自动完成的 QtQuick 文本搜索自动完成
【发布时间】:2019-08-06 20:31:13
【问题描述】:

我想在下面的链接中使用QML 创建一个外观相似的用户界面,这是我关于在pyqt5pyqt5 autocomplete QLineEdit - Google places autocomplete 中使用Qcompleter 的问题。我们如何在Qt Quick 中实现相同的模型,我似乎无法使用 QML 的TextField 中的模型,因为我收到以下错误

【问题讨论】:

  • 您是使用带有 QML 的 PyQt5 还是带有 QML 的 Qt C++?
  • 我使用 c++ 后端实现了该解决方案,该后端将检查匹配字段并返回一个列表。然后,您可以将该列表插入位于TextField 下方的listview(没有模型)。模型将作为建议/自动完成进入listview
  • @eyllanesc 我正在使用带有 QML 的 pyqt5

标签: python pyqt qml pyqt5


【解决方案1】:

使用之前的模型只需要创建 GUI,在这种情况下使用 ListView + Popup 实现选择逻辑:

ma​​in.py

import os
import sys
import json
from PyQt5 import QtCore, QtGui, QtNetwork, QtQml

API_KEY = "<API_KEY>"

class SuggestionPlaceModel(QtGui.QStandardItemModel):
    finished = QtCore.pyqtSignal()
    error = QtCore.pyqtSignal(str)
    countChanged = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(SuggestionPlaceModel, self).__init__(parent)
        self._manager = QtNetwork.QNetworkAccessManager(self)
        self._reply = None

    def count(self):
        return self.rowCount()

    count = QtCore.pyqtProperty(int, fget=count, notify=countChanged)

    @QtCore.pyqtSlot(str)
    def search(self, text):
        self.clear()
        self.countChanged.emit()
        if self._reply is not None:
            self._reply.abort()
        if text:
            r = self.create_request(text)
            self._reply = self._manager.get(r)
            self._reply.finished.connect(self.on_finished)
        loop = QtCore.QEventLoop()
        self.finished.connect(loop.quit)
        loop.exec_()

    def create_request(self, text):
        url = QtCore.QUrl("https://maps.googleapis.com/maps/api/place/autocomplete/json")
        query = QtCore.QUrlQuery()
        query.addQueryItem("key", API_KEY)
        query.addQueryItem("input", text)
        query.addQueryItem("types", "geocode")
        query.addQueryItem("language", "en")
        url.setQuery(query)
        request = QtNetwork.QNetworkRequest(url)
        return request

    @QtCore.pyqtSlot()
    def on_finished(self):
        reply = self.sender()
        if reply.error() == QtNetwork.QNetworkReply.NoError:
            data = json.loads(reply.readAll().data())
            if data['status'] == 'OK':
                for prediction in data['predictions']:
                    self.appendRow(QtGui.QStandardItem(prediction['description']))
            self.error.emit(data['status'])
        self.countChanged.emit()
        self.finished.emit()
        reply.deleteLater()
        self._reply = None

if __name__ == '__main__':
    app = QtGui.QGuiApplication(sys.argv)
    QtQml.qmlRegisterType(SuggestionPlaceModel, "PlaceModel", 1, 0, "SuggestionPlaceModel")
    engine = QtQml.QQmlApplicationEngine()
    qml_filename = os.path.join(os.path.dirname(__file__), 'main.qml')
    engine.load(QtCore.QUrl.fromLocalFile(qml_filename))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

ma​​in.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

import PlaceModel 1.0

ApplicationWindow {
    width: 400
    height: 400
    visible: true

    QtObject {
        id: internal
        property bool finished: false
        property bool busy: false
    }

    SuggestionPlaceModel{
        id: suggestion_model
        onFinished: {
            internal.busy = false
            if(count == 0) internal.finished = true
        }
    }

    TextField {
        anchors.centerIn: parent
        id: textfield
        onTextChanged: {
            internal.busy = true
            internal.finished = false
            Qt.callLater(suggestion_model.search, text)
        }
        Popup {
            id: popup
            y: parent.height
            visible: !internal.finished && textfield.length > 0
            closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
            contentItem: Loader{
                    sourceComponent: internal.busy ? busy_component: lv_component
                }
        }
    }

    Component{
        id: busy_component
        BusyIndicator {
            running: true
        }
    }

    Component{
        id: lv_component
        ListView {
            implicitWidth: contentItem.childrenRect.width
            implicitHeight: contentHeight
            model: suggestion_model
            delegate: Text {
                text: model.display
                MouseArea{
                    id: mousearea
                    anchors.fill: parent
                    hoverEnabled: true
                    onClicked: {
                        textfield.text = model.display
                        internal.finished = true
                    }
                }
            }
        }
    }
}

【讨论】:

  • 我收到 PlaceModel not found 错误..我错过了什么吗?
  • 是的,我都使用粘贴在同一个目录中
  • 我在 qtcreator qtquick 应用程序中运行这些
  • @Techiesoft 你不应该用 Qt Creator 运行它,你必须用 python 运行它:python /path/of/main.py
  • @Techiesoft 有 2 个选项,所以这取决于开发人员的口味。再见
猜你喜欢
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 2017-05-25
  • 1970-01-01
  • 2012-03-20
  • 2012-05-05
相关资源
最近更新 更多