Получение размера элемента (QStyledItemDelegate?) в QTableView в PyQt5?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Получение размера элемента (QStyledItemDelegate?) в QTableView в PyQt5?

Сообщение Anonymous »

В примере ниже (в конце статьи) я хочу
  • применить изображение к элементу QTableView ( ячейка), если она имеет пустое содержимое (как DecorationRole, поскольку у меня может быть другая логика, которая может использовать BackgroundRole)

    это изображение должно масштабироваться/изменять размер в соответствии с размером ячейки
[*]есть возможность произвольно запускать действия «resizeToContents»
[*]начать с таблица с «пустым» состоянием, представленным одной пустой ячейкой

Теперь, с приведенным ниже кодом, все обычно работает:
  • Изображение применяется к элементу (ячейке), если содержимое его данных пусто, и оно масштабируется вместе с ячейкой (например, если мы вручную изменяем ширину/высоту столбца/строки)
    "resizeToContents" обычно работает нормально, если ячейка содержит данные
Проблема связана с начальным «пустым» состоянием, рисунок DecorationRole и resizeToContents - позвольте мне проиллюстрировать:
  • Во-первых, если приведенный ниже код не делает изображение DecorationRole пустым ячейки/элементы (self.do_decoration = False), то при запуске мы получаем следующее состояние графического интерфейса:

    Изображение

    ... и после нажатия кнопки «resizeToContents» вместо этого мы получаем следующее состояние графического интерфейса:

    Изображение

    ... то есть ячейка «сжимается» (уменьшается ее ширина). Однако при последующих нажатиях на «resizeToContents» это второе состояние графического интерфейса остается неизменным (постоянным).
  • Однако, если мы сделаем включение изображения DecorationRole для пустых ячеек /предметы (self.do_decoration = True), то первое состояние графического интерфейса после запуска программы выглядит следующим образом:

    Изображение

    ... и при каждом последующем нажатии на "resizeToContents" ячейка/элемент растет - то есть после 5 кликов в "resizeToContents" состояние графического интерфейса выглядит следующим образом:

    Изображение
Поведение, которое я в противном случае хотел (и ожидал): если QTableView начинается с отображения одной ячейки с пустыми данными, и там нет изменений в данных ячейки, то независимо от того, сколько раз я нажимаю «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
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Получение размера элемента (QStyledItemDelegate?) в QTableView в PyQt5?
    Anonymous » » в форуме Python
    0 Ответы
    23 Просмотры
    Последнее сообщение Anonymous
  • В PyQT 5 всегда отображайте QCombobox, используя QStyledItemDelegate в QTableView (не только при редактировании ячейки)
    Anonymous » » в форуме Python
    0 Ответы
    28 Просмотры
    Последнее сообщение Anonymous
  • QStyledItemDelegate в QTableView смещен
    Anonymous » » в форуме Python
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • QStyledItemDelegate в QTableView смещен
    Anonymous » » в форуме Python
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous
  • QStyledItemDelegate в QTableView смещен
    Anonymous » » в форуме Python
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous

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