Изменение цвета фона отдельных меток строк (verticalHeader) в PyQt5 QTableView?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Изменение цвета фона отдельных меток строк (verticalHeader) в PyQt5 QTableView?

Сообщение Anonymous »

В моем приложении я хотел бы условно изменить цвет текста и фона произвольных меток строк (verticalHeader) QTableView.
В примере ниже для упрощения вещи, все, что я пытаюсь сделать, это изменить метку строки (verticalHeader) второй строки (т.е. строки с индексом или разделом 1) при нажатии кнопки - в частности, на красный цвет текста и зеленоватый цвет фона.
Насколько мне известно, способ сделать это в QTableView — это метод headerData с использованием Qt.TextColorRole и Qt.BackgroundRole, что я и сделал в примере ниже. При запуске приложения отображается следующее состояние графического интерфейса (в Windows 10, библиотеках MINGW64 Python3 и PyQt5):
[img]https://i .sstatic.net/0vOT31CY.png[/img]

... но после того, как я нажимаю кнопку «Переключить отображение метки строки», я получаю следующее:
Изображение

... где headerData Qt. TextColorRole работает (то есть цвет текста метки строки для второй строки становится красным, как и ожидалось), но Qt.BackgroundRole не работает (цвет фона метки строки для второй ряд нет изменить).
Итак, что я делаю неправильно, и как я могу изменить цвет фона метки строки для второй строки (надеюсь, без необходимости писать новый класс QHeaderView) )?
Похоже, это был давний вопрос (например, https://forum.qt.io/topic/28279 от 2013 года), но я никогда не находил ничего с простой, минимально воспроизводимый пример проблемы - и никаких решений - поэтому я подумал, что стоит спросить еще раз.
Пост Как управлять цветом фона заголовка в представлении таблицы с моделью? просто предлагает использовать QCSS; однако если вы раскомментируете строку self.table_view.setStyleSheet(table_view_qcss) в приведенном ниже примере, станет видно, что QCSS изменяет все метки заголовков – и точно такое же поведение воспроизводится при нажатии кнопки , просто с серыми метками заголовков в качестве отправной точки; поэтому после нажатия кнопки отображается следующее состояние графического интерфейса:
Изображение

... то есть опять же, headerData Qt.TextColorRole работает, Qt.BackgroundRole не работает.
Я заметил, что https://doc.qt.io/qt-5/qheaderview.html гласит:

Не все ItemDataRoles будут повлиять на QHeaderView. Если вам нужно отобразить другие роли, вы можете создать подкласс QHeaderView и переопределить PaintEvent(). QHeaderView учитывает следующие роли данных элемента: ...:
TextAlignmentRole, DisplayRole, FontRole, DecorationRole, ForegroundRole и BackgroundRole.

... что убедительно свидетельствует о том, что Qt.BackgroundRole должен работать; однако в приведенной выше цитате также опущена часть:

... если они не находятся в конфликте< /strong> со стилем (что может произойти со стилями, которые соответствуют теме рабочего стола)

... что затем подразумевает, почему Qt.BackgroundRole может не сработать.
Итак, я нашел Qt::BackgroundRole, похоже, игнорируется, а ответ намекает на следующее решение:

  • Для конкретного представления таблицы или заголовка используйте стиль, учитывающий кисти:
    //autokeys = QStyleFactory::keys();
    if(auto style = QStyleFactory:: создать("Слияние")) {
    verticalHeader()->setStyle(style);


Нечто подобное также упоминается в https://www.qtcentre.org/threads/13094- ... ta()-color:

В заголовке не используется делегат. Это очень ограниченный класс, поэтому, если вам нужно что-то необычное, вам придется создать подкласс QHeaderView и реализовать его самостоятельно. ...
Qt пытается следовать стилю платформы. Если Windows не позволяет изменять цвета заголовков, этого не произойдет. Вы можете запустить свое приложение с другим стилем (используя переключатель имени стиля -style, т. е. -style plastique) в Windows, и тогда оно, вероятно, будет работать. ...
Вы можете «схитрить» еще больше, изменив только стиль заголовка и оставив остальную часть приложения работать со стилем по умолчанию. Кстати, именно так работают таблицы стилей...

... но вы можете видеть, что в моем примере я попробовал сделать self.table_view .verticalHeader().setStyle(QStyleFactory.create("Fusion")), и похоже, это не имеет никакого значения (headerData Qt.BackgroundRole по-прежнему не может изменить цвет фона метки целевой строки).
Тот же ответ в Qt::BackgroundRole, похоже, игнорируется, также упоминается:< /p>

  • Вы также можете добиться этого, используя собственные делегаты элементов — наследовать от QStyledItemDelegate или что-то еще, переопределить один метод и настроить его для просмотра .


... но потом я вижу в https://doc.qt.io/qt-5 /qheaderview.html:

Примечание. Каждый заголовок отображает данные для каждого раздела сам по себе и не зависит от делегата. В результате вызов функции setItemDelegate() заголовка не будет иметь никакого эффекта
.

... поэтому теперь я действительно больше не знаю, что думать...
Итак, есть ли способ изменить цвет фона PyQt5 QTableView для произвольных меток строк, используя headerData и Qt.BackgroundRole?
Вот пример кода:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import (Qt, QSize, QPointF)
from PyQt5.QtGui import (QColor, QPalette, QPixmap, QBrush, QPen, QPainter)
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QPushButton, QStyleFactory)
# starting point from https://www.pythonguis.com/tutorials/qt ... py-pandas/

class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data, parview):
super(TableModel, self).__init__()
self._data = data
self._parview = parview # parent table view
#
def rowCount(self, index):
return len(self._data)
#
def columnCount(self, index):
return len(self._data[0])
#
def data(self, index, role):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]
if role == Qt.BackgroundRole: # https://stackoverflow.com/q/57321588
return QColor("#AA{:02X}{:02X}".format(
index.row()*20+100, index.column()*20+100
))
#
def headerData(self, section, orientation, role=Qt.DisplayRole): # https://stackoverflow.com/q/64287713
if orientation == Qt.Vertical:
if role == Qt.TextColorRole:
# only for the second row, where section == 1
if (section == 1) and (self._parview.rowLabelIndicate):
return QColor("red")
if role == Qt.BackgroundRole:
# only for the second row, where section == 1
if (section == 1) and (self._parview.rowLabelIndicate):
return QColor("#88FF88") #QBrush(QColor("#88FF88"))
#
# without the super call, no text is printed on header view labels!
return super().headerData(section, orientation, role)

class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.centralw = QWidget()
self.setCentralWidget(self.centralw)
self.vlayout = QVBoxLayout(self.centralw)
#
self.btn = QPushButton("Toggle row label indicate")
self.btn.clicked.connect(self.toggleRowLabelIndicate)
self.vlayout.addWidget(self.btn)
#
self.table_view = QtWidgets.QTableView()
self.table_view.rowLabelIndicate = False # dynamically added attribute/property
print(f"{QStyleFactory.keys()=}") # for me, it is: ['windowsvista', 'Windows', 'Fusion']
self.table_view.verticalHeader().setStyle(QStyleFactory.create("Fusion")) # passes here, no crash!
self.table_view.verticalHeader().setMinimumWidth(28) # int; seems to be in pixels
table_view_qcss = "QHeaderView::section { background-color:#DDDDDD }"
#self.table_view.setStyleSheet(table_view_qcss)
data = [
[ 1, 2, 3 ],
[ "hello", "world", "42" ],
[ 4, "more", "words" ],
]
self.model = TableModel(data, self.table_view)
self.table_view.setModel(self.model)
self.vlayout.addWidget(self.table_view)
#
self.resizeToContents()
#
def resizeToContents(self):
self.table_view.resizeColumnsToContents()
self.table_view.resizeRowsToContents()
#
def toggleRowLabelIndicate(self):
self.table_view.rowLabelIndicate = not(self.table_view.rowLabelIndicate)
change_row_start = change_row_end = 1
self.model.headerDataChanged.emit(Qt.Vertical, change_row_start, change_row_end)

app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
window.resize(180, 160)
app.exec_()


Подробнее здесь: https://stackoverflow.com/questions/791 ... in-pyqt5-q
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»