Изменение цвета 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_())
