Python中获取数据
添加数据处理类
main_win.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from PySide2.QtCore import QObject, Signal, Slot
class MainWin(QObject): userDataFetched = Signal(list)
@Slot() def fetchUserData(self): users = [ {"name": "张三", "age": 25}, {"name": "李四", "age": 30}, {"name": "王五", "age": 22}, {"name": "赵六", "age": 28} ] self.userDataFetched.emit(users)
|
注入属性
main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import sys from pathlib import Path
from PySide2.QtGui import QGuiApplication from PySide2.QtQml import QQmlApplicationEngine
from main_win import MainWin
if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() mainWin = MainWin() engine.rootContext().setContextProperty("mainWin", mainWin)
qml_file = Path(__file__).resolve().parent / "main.qml" engine.load(str(qml_file)) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
|
页面中使用
main.qml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| import QtQuick 2.15 import QtQuick.Controls 2.15
ApplicationWindow { visible: true width: 640 height: 480 title: "用户列表示例"
ListModel { id: userModel }
Button { text: "获取用户数据" anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter onClicked: { mainWin.fetchUserData() } }
ListView { anchors.top: parent.top anchors.topMargin: 50 anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right model: userModel delegate: Rectangle { width: ListView.view.width height: 60 color: index % 2 === 0 ? "lightgray" : "white" Row { spacing: 20 anchors.centerIn: parent Text { text: "用户名: " + name font.pixelSize: 18 } Text { text: "年龄: " + age font.pixelSize: 18 } } } }
Connections { target: mainWin function onUserDataFetched(users) { userModel.clear() for (var i = 0; i < users.length; i++) { userModel.append(users[i]) } } } }
|
子项要设置宽度和ListView一样,要用ListView.view.width。
QML中获取数据
main.qml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import QtQuick 2.15 import QtQuick.Controls 2.15
ApplicationWindow { visible: true width: 640 height: 480 title: "QML 用户列表示例"
ListModel { id: userModel ListElement { name: "张三" age: 25 } ListElement { name: "李四" age: 30 } }
Button { text: "显示用户数据" anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter onClicked: { listView.model = userModel; } }
ListView { id: listView anchors.top: parent.top anchors.topMargin: 50 anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right delegate: Rectangle { width: parent.width height: 60 color: index % 2 === 0 ? "lightgray" : "white" Row { spacing: 20 anchors.centerIn: parent Text { text: "用户名: " + name font.pixelSize: 18 } Text { text: "年龄: " + age font.pixelSize: 18 } } } } }
|
接口调用
在 QML 中发送带参数的 POST 请求,可以使用 XMLHttpRequest 或者 Qt.network 模块。
以下是两种方法的详细示例:
QML中 XMLHttpRequest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import QtQuick 2.15 import QtQuick.Controls 2.15
ApplicationWindow { visible: true width: 640 height: 480 title: "QML POST 请求示例"
Button { text: "调用接口" anchors.centerIn: parent onClicked: { callApi(); } }
Text { id: resultText anchors.top: parent.top anchors.topMargin: 50 anchors.horizontalCenter: parent.horizontalCenter font.pixelSize: 18 }
function callApi() { var xhr = new XMLHttpRequest(); xhr.open("POST", "https://example.com/api/endpoint"); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { var response = JSON.parse(xhr.responseText); resultText.text = "接口返回数据: " + JSON.stringify(response, null, 2); } else { resultText.text = "接口调用失败: " + xhr.statusText; } } };
var requestBody = JSON.stringify({ username: "user123", password: "password123" }); xhr.send(requestBody); } }
|
说明
xhr.open("POST", "接口URL") 用于初始化 POST 请求。
xhr.setRequestHeader("Content-Type", "application/json") 设置请求头的 Content-Type 为 JSON。
JSON.stringify 用于将 JavaScript 对象转换为 JSON 字符串。
xhr.send(requestBody) 用于发送请求体。
QML使用 Qt.network 模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Network 1.0
ApplicationWindow { visible: true width: 640 height: 480 title: "QML POST 请求示例"
Button { text: "调用接口" anchors.centerIn: parent onClicked: { networkManager.post(networkRequest); } }
Text { id: resultText anchors.top: parent.top anchors.topMargin: 50 anchors.horizontalCenter: parent.horizontalCenter font.pixelSize: 18 }
NetworkManager { id: networkManager onFinished: { if (reply.error === NetworkReply.NoError) { var response = JSON.parse(reply.readAll()); resultText.text = "接口返回数据: " + JSON.stringify(response, null, 2); } else { resultText.text = "接口调用失败: " + reply.errorString(); } } }
NetworkRequest { id: networkRequest url: "https://example.com/api/endpoint" method: "POST" header: { "Content-Type": "application/json" } body: JSON.stringify({ username: "user123", password: "password123" }) } }
|
说明
NetworkRequest 的 method 属性设置为 POST。
header 属性用于设置请求头,例如 Content-Type。
body 属性用于设置请求体,这里传递的是一个 JSON 字符串。
networkManager.post(networkRequest) 发送 POST 请求。
通过 Python(推荐复杂场景)
如果接口调用逻辑比较复杂,或者需要处理认证、加密等操作,可以通过 Python 后端调用接口,然后将结果传递给 QML。
Python 后端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import sys import requests from PySide2.QtGui import QGuiApplication from PySide2.QtQml import QQmlApplicationEngine from PySide2.QtCore import QObject, Signal, Slot
class ApiHandler(QObject): apiResponse = Signal(str)
@Slot() def callApi(self): url = "https://example.com/api/endpoint" payload = { "username": "user123", "password": "password123" } headers = { "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) if response.status_code == 200: self.apiResponse.emit(response.text) else: self.apiResponse.emit("接口调用失败: " + str(response.status_code))
if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine()
apiHandler = ApiHandler() engine.rootContext().setContextProperty("apiHandler", apiHandler)
engine.load("main.qml")
if not engine.rootObjects(): sys.exit(-1)
sys.exit(app.exec_())
|
QML 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import QtQuick 2.15 import QtQuick.Controls 2.15
ApplicationWindow { visible: true width: 640 height: 480 title: "QML POST 请求示例"
Button { text: "调用接口" anchors.centerIn: parent onClicked: { apiHandler.callApi(); } }
Text { id: resultText anchors.top: parent.top anchors.topMargin: 50 anchors.horizontalCenter: parent.horizontalCenter font.pixelSize: 18 text: "等待接口返回数据..." }
Connections { target: apiHandler onApiResponse: { resultText.text = "接口返回数据: " + response; } } }
|
说明
ApiHandler 是一个 Python 类,用于处理 POST 请求。
requests.post 是 Python 的 HTTP 请求库,用于发送 POST 请求。
apiResponse 是一个信号,用于将接口返回的数据传递给 QML。
Connections 用于监听 Python 后端的信号,并在 QML 中处理返回的数据。
总结
- 方法 1:适合简单的 HTTP POST 请求,直接在 QML 中使用 JavaScript 的
XMLHttpRequest。
- 方法 2:使用
Qt.network 模块,更符合 QML 的设计风格,推荐使用。
- 方法 3:适合复杂场景,通过 Python 后端调用接口,然后将结果传递给 QML。