如何在qml中的ListView中显示列表中的项目
How to display items in a list in ListView in qml
该代码应该获取数据库 table 中的行数并将其用作模型数,并在单击 btnShowList 后在 ListView 上显示所有行
但是,单击时没有任何反应。有两个文件。
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property var numberOfModels: 1
property var listofCust: []
Rectangle{
id: listViewContainer
color: "pink"
anchors.fill: parent
ListModel {
id: displayCustomers
ListElement{
firstName: "First Name"
LastName: "Last Name"
age: "Age"
Sex: "Sex"
}
}
Component{
id:customersDelegate
Row{
spacing: 50
Text{
text: firstName
}
Text {
text: LastName
}
Text {
text: age
}
Text {
text: Sex
}
}
}
ListView{
anchors.fill: parent
anchors.bottomMargin: 52
model: displayCustomers
delegate: customersDelegate
}
Button {
id: btnShowList
x: 518
y: 440
text: qsTr("show list")
onClicked: {
displayCustomers.append(backend.getCount)
}
}
}
Connections {
target: backend
function onGetCount(total, listofCust){
count = total
numberOfModels = total
listofCus = listofCust
return listofCust
}
}
}
main.py
import sys
import os
import mysql.connector
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Slot, Signal
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
count = Signal(int)
listOfCus = Signal([])
@Slot()
def getCount(self):
db = mysql.connector.connect(
host = "localhost",
user = "root",
passwd = "",
database = "test"
)
mycursor = db.cursor()
mycursor.execute("SELECT * FROM customer")
listofCustomers = []
total = 0
for x in mycursor:
total = total + 1
print(x)
listofCustomers.append(x)
self.count.emit(total)
print(total)
values = mycursor
print(values)
print(listofCustomers)
self.listOfCus.emit()
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
#Get Context
main = MainWindow()
engine.rootContext().setContextProperty("backend", main)
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
执行时没有错误。当我打印 listofCustomers 和 total 时,我得到了预期的输出。但是点击按钮后listView不显示任何东西
我认为您混淆了模型和委托是什么。您的模型应该包含要显示的数据。您的代表定义数据的显示方式。在您的示例中,您的代表不是视觉项目。看起来它正在检索数据,这些数据应该进入模型。这是它应该是什么样子的示例:
ListView {
// The model is the data
model: [2,4,6,8]
// The delegate is the view
delegate: Text {
text: modelData
}
}
OP 希望数据库信息神奇地显示在视图中,而至少不需要将该信息发送到 .qml。
另一方面,“displayCustomers.append (backend.getCount)”行令人困惑,您打算用该代码发生什么?在该代码中,getCount 函数被添加到模型中,这显然不合逻辑。
我们的想法是拥有一个模型(在 python 或 QML 中),其角色与委托所使用的角色相同,槽应仅用于填充模型,在这种情况下我将使用 python 模型。
import os
from pathlib import Path
import sys
import mysql.connector
from PySide2.QtCore import Property, QCoreApplication, QObject, Qt, QUrl, Slot
from PySide2.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PySide2.QtQml import QQmlApplicationEngine
CURRENT_DIRECTORY = Path(__file__).resolve().parent
FIRSTNAME_ROLE = Qt.UserRole
LASTNAME_ROLE = Qt.UserRole + 1
AGE_ROLE = Qt.UserRole + 2
SEX_ROLE = Qt.UserRole + 3
class Backend(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QStandardItemModel()
self._model.setItemRoleNames(
{
FIRSTNAME_ROLE: b"firstname",
LASTNAME_ROLE: b"lastname",
AGE_ROLE: b"age",
SEX_ROLE: b"sex",
}
)
self.add_row("Fistname", "LastName", "Age", "Sex")
def get_model(self):
return self._model
model = Property(QObject, fget=get_model, constant=True)
@Slot()
def loadFromDB(self):
self._model.clear()
db = mysql.connector.connect(
host="localhost", user="root", passwd="", database="test"
)
cursor = db.cursor()
cursor.execute("SELECT * FROM customer")
for row in cursor.fetchall():
firstname = row[0]
lastname = row[1]
age = row[2]
sex = row[3]
self.add_row(firstname, lastname, age, sex)
def add_row(self, firstname, lastname, age, sex):
item = QStandardItem()
item.setData(firstname, FIRSTNAME_ROLE)
item.setData(lastname, LASTNAME_ROLE)
item.setData(age, AGE_ROLE)
item.setData(sex, SEX_ROLE)
self._model.appendRow(item)
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
# Get Context
backend = Backend(app)
engine.rootContext().setContextProperty("backend", backend)
filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
url = QUrl.fromLocalFile(filename)
def handle_object_created(obj, obj_url):
if obj is None and url == obj_url:
QCoreApplication.exit(-1)
engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
engine.load(url)
sys.exit(app.exec_())
main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
Window {
property var numberOfModels: 1
property var listofCust: []
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
id: listViewContainer
color: "pink"
anchors.fill: parent
Component {
id: customersDelegate
Row {
spacing: 50
Text {
text: firstname
}
Text {
text: lastname
}
Text {
text: age
}
Text {
text: sex
}
}
}
ListView {
anchors.fill: parent
anchors.bottomMargin: 52
model: backend.model
delegate: customersDelegate
}
Button {
id: btnShowList
x: 518
y: 440
text: qsTr("show list")
onClicked: {
backend.loadFromDB();
}
}
}
}
该代码应该获取数据库 table 中的行数并将其用作模型数,并在单击 btnShowList 后在 ListView 上显示所有行 但是,单击时没有任何反应。有两个文件。
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property var numberOfModels: 1
property var listofCust: []
Rectangle{
id: listViewContainer
color: "pink"
anchors.fill: parent
ListModel {
id: displayCustomers
ListElement{
firstName: "First Name"
LastName: "Last Name"
age: "Age"
Sex: "Sex"
}
}
Component{
id:customersDelegate
Row{
spacing: 50
Text{
text: firstName
}
Text {
text: LastName
}
Text {
text: age
}
Text {
text: Sex
}
}
}
ListView{
anchors.fill: parent
anchors.bottomMargin: 52
model: displayCustomers
delegate: customersDelegate
}
Button {
id: btnShowList
x: 518
y: 440
text: qsTr("show list")
onClicked: {
displayCustomers.append(backend.getCount)
}
}
}
Connections {
target: backend
function onGetCount(total, listofCust){
count = total
numberOfModels = total
listofCus = listofCust
return listofCust
}
}
}
main.py
import sys
import os
import mysql.connector
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Slot, Signal
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
count = Signal(int)
listOfCus = Signal([])
@Slot()
def getCount(self):
db = mysql.connector.connect(
host = "localhost",
user = "root",
passwd = "",
database = "test"
)
mycursor = db.cursor()
mycursor.execute("SELECT * FROM customer")
listofCustomers = []
total = 0
for x in mycursor:
total = total + 1
print(x)
listofCustomers.append(x)
self.count.emit(total)
print(total)
values = mycursor
print(values)
print(listofCustomers)
self.listOfCus.emit()
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
#Get Context
main = MainWindow()
engine.rootContext().setContextProperty("backend", main)
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
执行时没有错误。当我打印 listofCustomers 和 total 时,我得到了预期的输出。但是点击按钮后listView不显示任何东西
我认为您混淆了模型和委托是什么。您的模型应该包含要显示的数据。您的代表定义数据的显示方式。在您的示例中,您的代表不是视觉项目。看起来它正在检索数据,这些数据应该进入模型。这是它应该是什么样子的示例:
ListView {
// The model is the data
model: [2,4,6,8]
// The delegate is the view
delegate: Text {
text: modelData
}
}
OP 希望数据库信息神奇地显示在视图中,而至少不需要将该信息发送到 .qml。
另一方面,“displayCustomers.append (backend.getCount)”行令人困惑,您打算用该代码发生什么?在该代码中,getCount 函数被添加到模型中,这显然不合逻辑。
我们的想法是拥有一个模型(在 python 或 QML 中),其角色与委托所使用的角色相同,槽应仅用于填充模型,在这种情况下我将使用 python 模型。
import os
from pathlib import Path
import sys
import mysql.connector
from PySide2.QtCore import Property, QCoreApplication, QObject, Qt, QUrl, Slot
from PySide2.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PySide2.QtQml import QQmlApplicationEngine
CURRENT_DIRECTORY = Path(__file__).resolve().parent
FIRSTNAME_ROLE = Qt.UserRole
LASTNAME_ROLE = Qt.UserRole + 1
AGE_ROLE = Qt.UserRole + 2
SEX_ROLE = Qt.UserRole + 3
class Backend(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QStandardItemModel()
self._model.setItemRoleNames(
{
FIRSTNAME_ROLE: b"firstname",
LASTNAME_ROLE: b"lastname",
AGE_ROLE: b"age",
SEX_ROLE: b"sex",
}
)
self.add_row("Fistname", "LastName", "Age", "Sex")
def get_model(self):
return self._model
model = Property(QObject, fget=get_model, constant=True)
@Slot()
def loadFromDB(self):
self._model.clear()
db = mysql.connector.connect(
host="localhost", user="root", passwd="", database="test"
)
cursor = db.cursor()
cursor.execute("SELECT * FROM customer")
for row in cursor.fetchall():
firstname = row[0]
lastname = row[1]
age = row[2]
sex = row[3]
self.add_row(firstname, lastname, age, sex)
def add_row(self, firstname, lastname, age, sex):
item = QStandardItem()
item.setData(firstname, FIRSTNAME_ROLE)
item.setData(lastname, LASTNAME_ROLE)
item.setData(age, AGE_ROLE)
item.setData(sex, SEX_ROLE)
self._model.appendRow(item)
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
# Get Context
backend = Backend(app)
engine.rootContext().setContextProperty("backend", backend)
filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
url = QUrl.fromLocalFile(filename)
def handle_object_created(obj, obj_url):
if obj is None and url == obj_url:
QCoreApplication.exit(-1)
engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
engine.load(url)
sys.exit(app.exec_())
main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
Window {
property var numberOfModels: 1
property var listofCust: []
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
id: listViewContainer
color: "pink"
anchors.fill: parent
Component {
id: customersDelegate
Row {
spacing: 50
Text {
text: firstname
}
Text {
text: lastname
}
Text {
text: age
}
Text {
text: sex
}
}
}
ListView {
anchors.fill: parent
anchors.bottomMargin: 52
model: backend.model
delegate: customersDelegate
}
Button {
id: btnShowList
x: 518
y: 440
text: qsTr("show list")
onClicked: {
backend.loadFromDB();
}
}
}
}