My code creates a scene for QGraphicsView that contains a QGraphicsProxyWidget inside of which is a QTableWidget. I have tried to scale the table and QGraphicsProxyWidget depending on the size of columns and rows, but I cannot achieve that the table always corresponds to the size of its contents and does not have scrolling, which hides rows or columns that simply do not fit.
from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon, QPixmap, QBrush
from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsRectItem, QGraphicsTextItem, \
QTableWidget, QTableWidgetItem, QGraphicsProxyWidget, QStyledItemDelegate
import sys
class ImageDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(ImageDelegate, self).__init__(parent)
def paint(self, painter, option, index):
pixmap = index.data(Qt.DecorationRole)
if pixmap:
rect = option.rect
scaled_pixmap = pixmap.scaled(rect.width(), rect.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
x = rect.x() + (rect.width() - scaled_pixmap.width()) / 2
y = rect.y() + (rect.height() - scaled_pixmap.height()) / 2
painter.drawPixmap(x, y, scaled_pixmap)
else:
super().paint(painter, option, index)
class Table(QTableWidget):
def __init__(self, rows, columns):
super().__init__(rows, columns)
self.setItemDelegate(ImageDelegate(self))
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
for i in range(rows):
for j in range(columns):
if i == 0 and j == 0: # Add an image to the first cell
item = QTableWidgetItem()
pixmap = QPixmap('D:\\User\\AaCePbBf.png') # Replace with the path to your image
if not pixmap.isNull(): # Check if the pixmap was successfully created
item.setData(Qt.DecorationRole, pixmap)
self.setItem(i, j, item)
else:
self.setItem(i, j, QTableWidgetItem(f"({j}, {i})"))
total_width = sum([self.columnWidth(i) for i in range(self.columnCount())])
total_height = sum([self.rowHeight(i) for i in range(self.rowCount())])
# Set the total width and height
self.setMinimumWidth(total_width)
self.setMinimumHeight(total_height)
app = QApplication(sys.argv)
scene = QGraphicsScene()
table = Table(10, 10)
proxy = QGraphicsProxyWidget()
proxy.setWidget(table)
proxy.setMinimumSize(table.minimumWidth(), table.minimumHeight())
scene.addItem(proxy)
view = QGraphicsView()
view.setScene(scene)
view.setSceneRect(0, 0, 5000, 5000)
view.show()
sys.exit(app.exec())
I know it's not normal to ask 2 questions, but is my mechanism for adding an image to a table cell OK? It seems to me that even small images lose a lot of quality due to image scaling.
from PySide6.QtCore import Qt, QSize
from PySide6.QtGui import QIcon, QPixmap, QBrush
from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsRectItem, QGraphicsTextItem, \
QTableWidget, QTableWidgetItem, QGraphicsProxyWidget, QStyledItemDelegate
import sys
class ImageDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
super(ImageDelegate, self).__init__(parent)
def sizeHint(self, option, index):
icon = index.data(Qt.DecorationRole)
if icon:
return QSize(128, 128) # Set the size of the icon to 128x128 pixels
else:
return super().sizeHint(option, index)
def paint(self, painter, option, index):
icon = index.data(Qt.DecorationRole)
if icon:
rect = option.rect
icon.paint(painter, rect, Qt.AlignCenter)
else:
super().paint(painter, option, index)
class Table(QTableWidget):
def __init__(self, rows, columns):
super().__init__(rows, columns)
self.setItemDelegate(ImageDelegate(self))
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
for i in range(rows):
for j in range(columns):
if i == 0 and j == 0: # Add an image to the first cell
item = QTableWidgetItem()
pixmap = QPixmap('D:\\User\\10101_gacksung_profile.png') # Replace with the path to your image
if not pixmap.isNull(): # Check if the pixmap was successfully created
icon = QIcon(pixmap)
item.setData(Qt.DecorationRole, icon)
self.setItem(i, j, item)
else:
self.setItem(i, j, QTableWidgetItem(f"({j}, {i})"))
self.resizeColumnsToContents()
self.resizeRowsToContents()
total_width = sum([self.columnWidth(i) for i in
range(self.columnCount())]) + self.verticalHeader().width() + 2 * self.frameWidth()
total_height = sum([self.rowHeight(i) for i in
range(self.rowCount())]) + self.horizontalHeader().height() + 2 * self.frameWidth()
self.setMinimumWidth(total_width)
self.setMinimumHeight(total_height)
app = QApplication(sys.argv)
scene = QGraphicsScene()
table = Table(15, 15)
proxy = QGraphicsProxyWidget()
proxy.setWidget(table)
scene.addItem(proxy)
view = QGraphicsView()
view.setScene(scene)
view.setSceneRect(0, 0, 5000, 5000)
view.show()
sys.exit(app.exec())
I was able to fix both problems although I'm not sure I did it correctly and in the best possible way. What I changed:
If you have anything to add or suggest, please write.