QStyledItemDelegate в QTableView смещенPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 QStyledItemDelegate в QTableView смещен

Сообщение Anonymous »

Я хочу показать список файлов со звездным рейтингом в QTableView. Для этого я использую следующий делегат:
class StarRatingDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)

def paint(self, painter, option, index):
file: File = index.data(Qt.UserRole)
star_rating_widget = StarRatingWidget(10, self.parent())
star_rating_widget.set_rating(file.rating)
star_rating_widget.render(painter, option.rect.topLeft())

StarRatingWidget Это простой QWidget, содержащий 5 QLables в QHBoxLayout.
Пока все работает, но все StarRatingWidgets сдвинуты в верхний левый угол:
Изображение

В первом столбце отображается рейтинг в виде числа. Вы можете видеть, что все звезды слегка смещены влево и чуть больше, чем на одну высоту строки вверх.
Тесты показали, что option.rect возвращает координаты с помощью (0, 0) — верхний левый угол первой ячейки, но star_rating_widget.render обрабатывает координаты так, что (0, 0) — верхний левый угол окна. Таким образом, виджеты смещаются на расстояние между таблицей и границей окна, а также на высоту заголовка таблицы.
Прежде чем кто-то спросит, вот полный код. Для запуска требуется pyside6.
#!/usr/bon/env python

from PySide6.QtCore import Qt, Signal, QAbstractItemModel, QModelIndex, QEvent
from PySide6.QtGui import QMouseEvent
from PySide6.QtWidgets import QApplication, QLabel, QTableView, QMainWindow, QSizePolicy, QHBoxLayout, QWidget, QStyledItemDelegate

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setGeometry(100, 100, 250, 600)

self.central_widget = QWidget()
self.main_layout = QHBoxLayout()
self.central_widget.setLayout(self.main_layout)
self.setCentralWidget(self.central_widget)

self.list = QTableView()
self.list.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
self.list.setSelectionMode(QTableView.SelectionMode.SingleSelection)
self.list.horizontalHeader().setStretchLastSection = True
self.list.verticalHeader().hide()
self.list.show_grid = False
self.list.setItemDelegateForColumn(1, StarRatingDelegate(self.list))
self.list.setModel(ListModel())
self.main_layout.addWidget(self.list)

class ListModel(QAbstractItemModel):
def __init__(self):
super().__init__()
self.horizontal_header_labels = ['Number', 'Stars']

def rowCount(self, parent=QModelIndex()):
return 50

def columnCount(self, parent=QModelIndex()):
return len(self.horizontal_header_labels)

def data(self, index, role):
if not index.isValid():
return None
if role == Qt.DisplayRole:
rating = (index.row() - 2) % 7
return None if rating >= 5 else rating + 1
return None

def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.horizontal_header_labels[section]
return None

def index(self, row, column, parent=QModelIndex()):
if self.hasIndex(row, column, parent):
return self.createIndex(row, column)
return QModelIndex()

def parent(self, index):
return QModelIndex()

class StarRatingWidget(QWidget):
rating_changed = Signal(int)

def __init__(self, font_size, parent=None):
super().__init__(parent)
self.rating = 0
self.hovered_star: int|None = None
self.stars: List[QLabel] = []
self.font_size: int = font_size
self.init_ui()

def star_mouse_event(self, i: int):
def event(event: QMouseEvent):
if event.type() == QEvent.Enter:
self.hovered_star = i
self.update()
elif event.type() == QEvent.Leave:
self.hovered_star = None
self.update()
return event

def init_ui(self):
layout = QHBoxLayout()
for i in range(5):
star = QLabel()
star.mousePressEvent = lambda _, i=i: self.set_rating(i + 1)
star.enterEvent = self.star_mouse_event(i)
star.leaveEvent = self.star_mouse_event(i)
star.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
layout.addWidget(star)
self.stars.append(star)
self.setLayout(layout)
self.update()

def set_rating(self, rating: int|None):
if rating != self.rating:
self.rating = rating
self.update()
self.rating_changed.emit(rating)

def update(self):
for i, star in enumerate(self.stars):
rating = self.rating if self.rating is not None else 0
if i < rating:
star.setText('★')
else:
star.setText('☆')

if self.rating is None:
color = 'gray'
weight = 'normal'
elif i == self.hovered_star:
color = 'blue'
weight = 'bold'
else:
color = 'yellow'
weight = 'normal'

star.setStyleSheet(f'font-size: {self.font_size}px; color: {color}; font-weight: {weight}')

class StarRatingDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)

def paint(self, painter, option, index):
rating = index.data()
star_rating_widget = StarRatingWidget(10, self.parent())
star_rating_widget.set_rating(rating)
star_rating_widget.render(painter, option.rect.topLeft())

def main():
app = QApplication([])
main_window = MainWindow()
main_window.show()
QApplication.exec()

if __name__ == '__main__':
main()


Подробнее здесь: https://stackoverflow.com/questions/793 ... misaligned
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

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

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