Если структура имеет древовидный тип, то модель должна иметь эту структуру, чтобы можно было использовать модель, основанную на QAbstractItemModel, но для упрощения я реализовал ее с помощью класса QStandardItemModel, где я установил значения в соответствующих ролях, и так, что индикатор выполнения отображается в новом файле, поэтому вы должны быть дочерним элементом этого элемента. Чтобы показать индикатор выполнения, я не установил виджет, но он был нарисован с использованием QStyle через делегата:
from PySide2.QtCore import Qt
from PySide2.QtGui import QIcon, QStandardItem, QStandardItemModel
class UserModel(QStandardItemModel):
def __init__(self, parent=None):
super(UserModel, self).__init__(parent)
self.setColumnCount(4)
def appendUser(self, id_, name, image, details, progress):
items = []
row = self.rowCount()
for text, column in zip((id_, name, details), (0, 1, 3)):
it = QStandardItem()
it.setData(text, Qt.DisplayRole)
self.setItem(row, column, it)
items.append(it)
image_item = QStandardItem()
image_item.setData(QIcon(image), Qt.DecorationRole)
self.setItem(row, 2, image_item)
progress_item = QStandardItem()
progress_item.setData(progress, Qt.UserRole)
items[0].appendRow(progress_item)
import os
import sys
from PySide2.QtCore import QSize, Qt
from PySide2.QtWidgets import (
QApplication,
QMainWindow,
QHeaderView,
QStyledItemDelegate,
QStyleOptionProgressBar,
QStyle,
)
from TreeViewUI import Ui_MainWindow
from custom_models.table_model import UserModel
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class ProgressDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
if index.parent().isValid():
r = option.rect
r.setWidth(200)
progress = index.data(Qt.UserRole)
progress_option = QStyleOptionProgressBar()
progress_option.rect = r
progress_option.minimum = 0
progress_option.maximum = 100
progress_option.progress = progress
progress_option.text = "{}%".format(progress)
progress_option.textVisible = True
QApplication.style().drawControl(
QStyle.CE_ProgressBar, progress_option, painter
)
return
super(ProgressDelegate, self).paint(painter, option, index)
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, data):
super(MainWindow, self).__init__()
self.setupUi(self)
self.model = UserModel(self)
for content_data in data:
self.model.appendUser(
content_data["user_id"],
content_data["user_name"],
os.path.join(CURRENT_DIR, content_data["user_image"]),
content_data["user_details"],
content_data["user_progress"],
)
self.treeView.setIconSize(QSize(360 / 4, 640 / 4))
self.treeView.header().setSectionResizeMode(QHeaderView.ResizeToContents)
self.treeView.setModel(self.model)
delegate = ProgressDelegate(self.treeView)
self.treeView.setItemDelegate(delegate)
def get_data():
content_list = [
{
"user_id": 101,
"user_name": "User_1",
"user_image": "images/demo.jpg",
"user_details": "details_1",
"user_progress": 45,
},
{
"user_id": 102,
"user_name": "User_2",
"user_image": "images/demo.jpg",
"user_details": "details_2",
"user_progress": 33,
},
{
"user_id": 103,
"user_name": "User_3",
"user_image": "images/demo.jpg",
"user_details": "details_3",
"user_progress": 80,
},
]
return content_list
if __name__ == "__main__":
app = QApplication([])
data = get_data()
main_window = MainWindow(data)
main_window.showMaximized()
sys.exit(app.exec_())
Другой Возможное решение - создать постоянный редактор через делегата:
class ProgressDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
if index.parent().isValid():
view = option.widget
if isinstance(view, QTreeView) and index.model() is view.model():
view.openPersistentEditor(index)
return
super(ProgressDelegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
if index.parent().isValid():
editor = QProgressBar(parent)
editor.setFixedWidth(200)
editor.setContentsMargins(0, 0, 0, 0)
editor.setValue(index.data(Qt.UserRole))
return editor
super(ProgressDelegate, self).createEditor(parent, option, index)
Примечание: Рисование QProgressBar, как я делал в первом делегате, является тривиальной задачей, но если вы хотите разместить больше сложные виджеты (виджеты, которые имеют больше состояний, таких как QPushButton), тогда лучше использовать второй вариант.