Изменение цвета QProgressBar Delegate

Хочу сделать ход выполнения процесса QProgressBar в QTableView - это уже получилось.

Теперь хочу добавить изменение цвета при остановке процесса, но не пойму как это сделать с делегатом.

Пробовал через установку нового делегата, но он не работает (не перерисовывает цвет).
Пробовал устанавливать стандартный делегат, но так же, изменений никаких.

В делегате нет диапазона, т.е. setRange(0, 0) процесс либо идёт (зелёный), либо нет (красный).

Полный пример:

from PySide2 import QtCore, QtWidgets, QtGui
import os

class ProgressBarDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent, color):
        super(ProgressBarDelegate, self).__init__(parent)
        self.color = color

    def paint(self, painter, option, index):
        if index.column() == 2:
            if (isinstance(self.parent(), QtWidgets.QAbstractItemView)
                    and self.parent().model() is index.model()):
                self.parent().openPersistentEditor(index)
            QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)
        else:
            QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)

    def createEditor(self, parent: QtWidgets.QWidget, option: QtWidgets.QStyleOptionViewItem,
                     index: QtCore.QModelIndex) -> QtWidgets.QWidget:
        editor = QtWidgets.QProgressBar(parent)
        editor.setRange(0, 0)
        editor.setTextVisible(False)
        editor.setStyleSheet("QProgressBar:chunk {background-color:" + self.color + "; width: 20px; margin: 0.5px}")

        return editor

class PushButtonDelegate(QtWidgets.QStyledItemDelegate):
    clicked = QtCore.Signal(QtCore.QModelIndex)

    def paint(self, painter, option, index):
        if (isinstance(self.parent(), QtWidgets.QAbstractItemView)
                and self.parent().model() is index.model()):
            self.parent().openPersistentEditor(index)
        QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)

    def createEditor(self, parent, option, index):
        button = QtWidgets.QPushButton(parent)
        button.clicked.connect(lambda *args, ix=index: self.clicked.emit(ix))

        return button

    def setEditorData(self, editor, index):
        editor.setText("...")

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)


class MyWidgetsForm(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)

        self.initUi()
        self.initModel()

        self.pbDelegate.clicked.connect(self.onPBDelegateClicked)

    def onPBDelegateClicked(self, pushRow):
        print(self.tableView.model().index(pushRow.row(), 2).data())
        if self.tableView.model().index(pushRow.row(), 2).data() is None or self.tableView.model().index(pushRow.row(), 2).data() == 0:
            prbarDelegate = ProgressBarDelegate(self.tableView, "green")
            self.tableView.setItemDelegateForRow(pushRow.row(), prbarDelegate)

            self.tableView.model().setData(self.tableView.model().index(pushRow.row(), 2), 1,
                                              QtCore.Qt.DisplayRole)

        elif self.tableView.model().index(pushRow.row(), 2).data() == 1:
            prbarDelegate = ProgressBarDelegate(self.tableView, "red")
            self.tableView.setItemDelegateForRow(pushRow.row(), prbarDelegate)

            self.tableView.model().setData(self.tableView.model().index(pushRow.row(), 2), 0,
                                              QtCore.Qt.DisplayRole)

    def initUi(self):
        self.setFixedSize(600, 300)

        self.tableView = QtWidgets.QTableView()
        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(self.tableView)
        cw = QtWidgets.QWidget()
        cw.setLayout(layout)
        self.setCentralWidget(cw)

    def initModel(self):
        headers = ['Путь', 'Управление', 'Прогресс']
        self.pbDelegate = PushButtonDelegate(self.tableView)

        self.stm = QtGui.QStandardItemModel()
        self.stm.setHorizontalHeaderLabels(headers)

        for row in range(5):
            self.stm.setItem(row, 0, QtGui.QStandardItem("some_path"+str(row)))
            self.stm.setItem(row, 1, QtGui.QStandardItem())


        self.tableView.setModel(self.stm)
        self.tableView.clearSpans()
        self.tableView.setItemDelegateForColumn(1, self.pbDelegate)
        self.tableView.resizeColumnsToContents()
        self.tableView.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)


if __name__ == "__main__":
    app = QtWidgets.QApplication()

    myapp = MyWidgetsForm()
    myapp.show()

    app.exec_()

Ответы (1 шт):

Автор решения: S. Nick

Вот вам реализация вашей задумки с использованием виджета QTableWidget.

import sys
from PyQt5.Qt import *


class MyWidgetsForm(QMainWindow):
    def __init__(self):
        super().__init__()  
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)

        headers = ['Путь', 'Управление', 'Прогресс']
        self.tableWidget = QTableWidget(0, 3)
        self.tableWidget.setHorizontalHeaderLabels(headers) 
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        for row in range(5):
            rowPosition = self.tableWidget.rowCount()
            self.tableWidget.insertRow(rowPosition)
            self.tableWidget.setItem(rowPosition, 0, QTableWidgetItem(f"some_path: {row}"))        

            progressBar = QProgressBar(objectName="progressBar")
            progressBar.setRange(0, 0)
            progressBar.setTextVisible(False)

            button = QPushButton(f'btn{row}')
            button.setCheckable(True)
            button.clicked.connect(
                lambda ch, 
                       w_pb=progressBar,       
                       r=row, 
                       c=1 : self.button_pushed(ch, w_pb, r, c)  
            )                
            self.tableWidget.setCellWidget(row, 1, button)
            self.tableWidget.setCellWidget(row, 2, progressBar)

        self.tableWidget.cellClicked.connect(self.row_column_clicked)
        
        layout = QVBoxLayout(self.centralWidget)
        layout.addWidget(self.tableWidget)

    def button_pushed(self, state, w_pb, r, c): 
        print(f'clicked: row={r}, column={c}')
        if state:
            w_pb.setStyleSheet('''
                #progressBar {border: 2px solid #2196F3; min-height: 22px;}
                #progressBar::chunk {background-color: green;}
            ''')
        else:
            w_pb.setStyleSheet('''
                #progressBar {border: 2px solid #2196F3; min-height: 22px;}
                #progressBar::chunk {background-color: red;}
            ''')

    def row_column_clicked(self, row, column):  
        print(f'clicked: row={row}, column={column}')
        

StyleSheet = '''
#progressBar {
    border: 0px solid #2196F3;   
    border-radius: 5px;
    background-color: #E0E0E0;
    min-height: 0px;
    max-height: 0px;
}
#progressBar::chunk {
    background-color: #2196F3;
    width: 10px;               
    margin: 0.5px;
}
'''


if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyleSheet(StyleSheet)
    w = MyWidgetsForm()
    w.setWindowTitle("Title MainWindow")
    w.resize(600, 300)
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка