- применить изображение к элементу QTableView ( ячейка), если она имеет пустое содержимое (как DecorationRole, поскольку у меня может быть другая логика, которая может использовать BackgroundRole)
это изображение должно масштабироваться/изменять размер в соответствии с размером ячейки
[*]начать с таблица с «пустым» состоянием, представленным одной пустой ячейкой
Теперь, с приведенным ниже кодом, все обычно работает:
- Изображение применяется к элементу (ячейке), если содержимое его данных пусто, и оно масштабируется вместе с ячейкой (например, если мы вручную изменяем ширину/высоту столбца/строки)
"resizeToContents" обычно работает нормально, если ячейка содержит данные
- Во-первых, если приведенный ниже код не делает изображение DecorationRole пустым ячейки/элементы (self.do_decoration = False), то при запуске мы получаем следующее состояние графического интерфейса:
... и после нажатия кнопки «resizeToContents» вместо этого мы получаем следующее состояние графического интерфейса:
... то есть ячейка «сжимается» (уменьшается ее ширина). Однако при последующих нажатиях на «resizeToContents» это второе состояние графического интерфейса остается неизменным (постоянным). - Однако, если мы сделаем включение изображения DecorationRole для пустых ячеек /предметы (self.do_decoration = True), то первое состояние графического интерфейса после запуска программы выглядит следующим образом:
... и при каждом последующем нажатии на "resizeToContents" ячейка/элемент растет - то есть после 5 кликов в "resizeToContents" состояние графического интерфейса выглядит следующим образом:
Тот факт, что состояние графического интерфейса изменяется в случае «no DecorationRole» при запуске, не является проблемой: я думаю, «resizeToContents» также учитывает содержимое меток «1» в заголовках строк и столбцов и изменяет размеры всего в соответствии с к этому - что можно решить, запустив «resizeToContents» один раз в init; тогда пользователь не увидит никаких изменений при нажатии «resizeToContents» после запуска программы.
Однако постоянное увеличение размера ячейки в случае «да DecorationRole» является проблемой; на мой взгляд, это связано с тем, что я не могу получить размер ячейки/элемента, поскольку в QTableView ячейки/элементы даже не являются QWidget - они QStyledItemDelegate< /code>, у которого нет методов для получения или установки ширины или высоты элемента. И поэтому я попытался обойти код, используя QTableView.rowHeight и QTableView.columnWidth - но они, очевидно, возвращают размеры, которые немного больше, чем фактические размеры ячейки/элемента, и поэтому растровое изображение DecorationRole в конечном итоге оказывается немного больше фактического размера ячейки/элемента - поэтому в следующий раз, когда "resizeToContents" он пытается это учесть, но затем генерируется новое, еще большее растровое изображение украшения - и мы в конечном итоге получаем своего рода рекурсивное увеличение размер ячейки.
Вот почему в конечном итоге у меня возникает вопрос: как мне получить фактический размер элемента (ячейки) QStyledItemDelegate в QTableView? Я предполагаю, что если бы я мог создать растровое изображение с фактическим размером ячейки, то последующие вызовы «resizeToContents» больше не увеличивали бы размер ячейки, и все работало бы так, как я себе представлял.
Вот код:
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, QStyleOptionViewItem, QStyledItemDelegate)
# 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
self.do_decoration = True
#
def create_pixmap(self, pic_qsize): # SO:62799632
pixmap = QPixmap(pic_qsize)
pixmap.fill(QColor(0,0,0,0))
painter = QPainter()
painter.begin(pixmap)
#painter.setBrush(QtGui.QBrush(QtGui.QColor("blue")))
painter.setPen(QPen(QColor("#446600"), 4, Qt.SolidLine))
painter.drawLine(pixmap.rect().bottomLeft(), pixmap.rect().center()+QPointF(0,4))
painter.drawLine(pixmap.rect().bottomRight(), pixmap.rect().center()+QPointF(0,4))
painter.drawLine(pixmap.rect().topLeft(), pixmap.rect().center()+QPointF(0,-4))
painter.drawLine(pixmap.rect().topRight(), pixmap.rect().center()+QPointF(0,-4))
painter.end()
return pixmap
#
def data(self, index, role):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]
if self.do_decoration and role == Qt.DecorationRole: # SO:74203503
value = self._data[index.row()][index.column()]
if not(value):
row_height = self._parview.rowHeight(index.row()) #-5
column_width = self._parview.columnWidth(index.column()) #-13
#item = self._parview.itemDelegate(index) # QStyledItemDelegate
print(f"{row_height=} {column_width=}")
pic_qsize = QSize(column_width, row_height)
return self.create_pixmap(pic_qsize)
#
def rowCount(self, index):
return len(self._data)
#
def columnCount(self, index):
return len(self._data[0])
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.centralw = QWidget()
self.setCentralWidget(self.centralw)
self.vlayout = QVBoxLayout(self.centralw)
#
self.btn = QPushButton("resizeToContents")
self.btn.clicked.connect(self.resizeToContents)
self.vlayout.addWidget(self.btn)
#
self.table_view = QtWidgets.QTableView()
data = [ [ "" ] ]
self.model = TableModel(data, self.table_view)
self.table_view.setModel(self.model)
self.vlayout.addWidget(self.table_view)
#
#
def resizeToContents(self):
self.table_view.resizeColumnsToContents()
self.table_view.resizeRowsToContents()
app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
window.resize(280, 140)
app.exec_()
Подробнее здесь: https://stackoverflow.com/questions/791 ... w-in-pyqt5