Qt Quick列表及数据加载

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):
# 定义一个信号,用于向 QML 传递用户列表数据
userDataFetched = Signal(list)

@Slot()
def fetchUserData(self):
# 模拟从后端获取用户数据(用户名和年龄)
users = [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30},
{"name": "王五", "age": 22},
{"name": "赵六", "age": 28}
]
# 通过信号将数据传递给 QML
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
# This Python file uses the following encoding: utf-8
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()
# 将后端对象暴露给 QML 上下文
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
}

// 按钮:点击后调用后端的 fetchUserData 方法
Button {
text: "获取用户数据"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
mainWin.fetchUserData() // 调用 Python 后端的 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"); // 替换为您的接口 URL
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" // 替换为您的接口 URL
method: "POST"
header: {
"Content-Type": "application/json"
}
body: JSON.stringify({
username: "user123",
password: "password123"
})
}
}

说明

  • NetworkRequestmethod 属性设置为 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):
# 定义信号:用于将接口返回的数据传递给 QML
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 = ApiHandler()
engine.rootContext().setContextProperty("apiHandler", apiHandler)

# 加载 QML 文件
engine.load("main.qml")

# 检查 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: {
// 调用 Python 后端的接口
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。