Issue
i did create a qtableview in which column 1 has images and successfully made ImageDelegate that handles showing images in cells but the problem is with showing them with original ratio they appear to be stretched and maybe a bit smaller
image example:
the sample database used: https://gofile.io/d/LKNdsi the code:
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout, QCheckBox, QTableWidgetItem, QAbstractItemView, QTableWidget, QTableView, QStyledItemDelegate)
import sqlite3
class Main(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.table = QtWidgets.QTableView()
conn = sqlite3.connect("math.db")
conn.text_factory = bytes
self.cur = conn.cursor()
data = self.cur.execute("select * from problems;").fetchall();conn.close()
self.dims = (lambda x: (len(x), len(x[0])))(data) #(rows number, col number)
self.model = TableModel([[j.decode("utf-8", "ignore") if u!=1 else j for u, j in enumerate(i)] for i in data])
self.table.setModel(self.model)
self.table.setItemDelegateForColumn(1, ImageDelegate(self))
#self.table.resizeColumnsToContents()
#self.table.resizeRowsToContents()
self.setCentralWidget(self.table)
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def data(self, index, role):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]
def rowCount(self, index):
return len(self._data)
def columnCount(self, index):
return len(self._data[0])
class ImageDelegate(QStyledItemDelegate):
def __init__(self, parent):
QStyledItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
## [ Here is the part that needs something added or fixed ]
pixmap = QtGui.QPixmap()
pixmap.loadFromData(index.data(), "jpg")
painter.drawPixmap(option.rect, pixmap)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.resize(600,600)
main.show()
app.exec_()
and here is a snippet code i used to use with QtableWidget that fixed this issue for me in old days but now with QtableView things appears to be different somehow. snippt class:
class ScaledPixmapLabel(QtWidgets.QLabel):
def __init__(self):
super().__init__()
self.setScaledContents(True)
def paintEvent(self, event):
if self.pixmap():
pm = self.pixmap()
originalRatio = pm.width() / pm.height()
currentRatio = self.width() / self.height()
if originalRatio != currentRatio:
qp = QtGui.QPainter(self)
pm = self.pixmap().scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
rect = QtCore.QRect(0, 0, pm.width(), pm.height())
rect.moveCenter(self.rect().center())
qp.drawPixmap(rect, pm)
return
super().paintEvent(event)
Solution
You have to make the size of column "1" and all its rows depend on the content, that is, on the image. On the other hand, instead of making a personalized painting, I established it as an icon. Also implement that the icon is placed in the center:
from PyQt5 import QtWidgets, QtGui, QtCore
import sqlite3
class ImageDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(ImageDelegate, self).initStyleOption(option, index)
pixmap = QtGui.QPixmap()
pixmap.loadFromData(index.data(), "jpg")
if not pixmap.isNull():
option.features |= QtWidgets.QStyleOptionViewItem.HasDecoration
option.icon = QtGui.QIcon(pixmap)
option.decorationSize = pixmap.size() / pixmap.devicePixelRatio()
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return self._data[index.row()][index.column()]
def rowCount(self, index):
return len(self._data)
def columnCount(self, index):
return len(self._data[0])
class ImageCenterProxyStyle(QtWidgets.QProxyStyle):
def subElementRect(self, subElement, option, widget=None):
r = super(ImageCenterProxyStyle, self).subElementRect(
subElement, option, widget
)
if subElement == QtWidgets.QStyle.SE_ItemViewItemDecoration:
r.moveCenter(option.rect.center())
return r
class Main(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.table = QtWidgets.QTableView()
conn = sqlite3.connect("math.db")
conn.text_factory = bytes
self.cur = conn.cursor()
data = self.cur.execute("select * from problems;").fetchall()
conn.close()
self.dims = (lambda x: (len(x), len(x[0])))(data) # (rows number, col number)
self.model = TableModel(
[
[j.decode("utf-8", "ignore") if u != 1 else j for u, j in enumerate(i)]
for i in data
]
)
self.table.setModel(self.model)
self.table.setItemDelegateForColumn(1, ImageDelegate(self))
self.table.resizeRowsToContents()
self.table.horizontalHeader().setSectionResizeMode(
1, QtWidgets.QHeaderView.ResizeToContents
)
proxy = ImageCenterProxyStyle(self.table.style())
self.table.setStyle(proxy)
self.setCentralWidget(self.table)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.resize(600, 600)
main.show()
app.exec_()
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.