alphanumeric
alphanumeric

Reputation: 19329

How to change QTableView image size

Model's data() properly assigns a scaled to 64x64 pixmap to each QModelIndex. But the monkey gets clipped since the row's height is too short. The two lines below resize only the second row (why only second?!):

    self.tableviewA.resizeColumnToContents(True)
    self.tableviewA.resizeRowToContents(True)

enter image description here

Sure I can iterate each row and setRowHeight(row, heightInt) manually. But that would be an extra calculation for the machine to perform. I wonder if there is a better simpler way to make QTableView to resize each row to fit the thumb (or any other context) populating it...

Here is the link to monkey icon required to run the example code posted below (right-click to save it as "monkey.png" to the same folder from where a script is run):

enter image description here

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.images = ['monkey.png','monkey.png','monkey.png']
        self.items = ['Row0_Column0','Row0_Column1','Row0_Column2']

        self.thumbSize=64

    def resizePixmap(self, mult):
        self.thumbSize=self.thumbSize*mult
        self.reset()

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 3

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        row=index.row()
        if row>len(self.items): return QVariant()

        if role == Qt.DisplayRole:
            return QVariant(self.items[row])

        elif role == Qt.DecorationRole:

            image=self.images[row]
            pixmap=QPixmap(image).scaled(QSize(self.thumbSize, self.thumbSize), Qt.KeepAspectRatio)
            return pixmap

        return QVariant()

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():            
            if role == Qt.EditRole:                
                row = index.row()
                self.items[row]=value  
                return True
        return False

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        self.tablemodel=Model(self)               

        self.tableviewA=QTableView() 
        self.tableviewA.setModel(self.tablemodel)   

        buttonPlus=QPushButton('Plus')
        buttonMinus=QPushButton('Minus') 

        buttonPlus.clicked.connect(self.plus)
        buttonMinus.clicked.connect(self.minus)

        layout = QVBoxLayout(self)
        layout.addWidget(self.tableviewA)
        layout.addWidget(buttonPlus)
        layout.addWidget(buttonMinus)
        self.setLayout(layout)

        self.tableviewA.resizeColumnToContents(True)
        self.tableviewA.resizeRowToContents(True)

    def plus(self, arg):
        self.tablemodel.resizePixmap(1.1)

        thumbSize=self.tableviewA.model().thumbSize 
        totalRows=self.tablemodel.rowCount(QModelIndex())
        for row in range(totalRows):
            self.tableviewA.setRowHeight(row, thumbSize*1.1)

    def minus(self, arg):
        self.tablemodel.resizePixmap(0.9)

        thumbSize=self.tableviewA.model().thumbSize 
        totalRows=self.tablemodel.rowCount(QModelIndex())
        for row in range(totalRows):
            self.tableviewA.setRowHeight(row, thumbSize*0.9)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

Upvotes: 1

Views: 3694

Answers (1)

alphanumeric
alphanumeric

Reputation: 19329

The problem was in not using

self.tableviewA.resizeRowsToContents()
self.tableviewA.resizeColumnsToContents()

methods which reset the row heights and column widths respectively. In the solution posted below I have included a elif role == Qt.SizeHintRole:... too (here for the educational purposes).

enter image description here

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.images = ['monkey.png','monkey.png','monkey.png']
        self.items = ['Row0_Column0','Row0_Column1','Row0_Column2']

        self.thumbSize=64

    def resizePixmap(self, mult):
        self.thumbSize=self.thumbSize*mult
        self.reset()

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 3

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        row=index.row()
        if row>len(self.items): return QVariant()

        if role == Qt.DisplayRole:
            return QVariant(self.items[row])

        elif role == Qt.DecorationRole:
            image=self.images[row]
            pixmap=QPixmap(image).scaled(QSize(self.thumbSize, self.thumbSize), Qt.KeepAspectRatio)
            return pixmap

        elif role == Qt.SizeHintRole:
            print 'Model.data(role == Qt.SizeHintRole) row: %s; column %s'%(index.row(), index.column())
            # return QSize(32, 32)

        return QVariant()

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():            
            if role == Qt.EditRole:                
                row = index.row()
                self.items[row]=value  
                return True
        return False


class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        self.tablemodel=Model(self)               

        self.tableviewA=QTableView() 
        self.tableviewA.setModel(self.tablemodel)   

        buttonResize=QPushButton('Resize')
        buttonZoomIn=QPushButton('Zoom In')
        buttonZoomOut=QPushButton('Zoom Out') 

        buttonResize.clicked.connect(self.resizeView)
        buttonZoomIn.clicked.connect(self.zoomIn)
        buttonZoomOut.clicked.connect(self.zoomOut)

        layout = QVBoxLayout(self)
        layout.addWidget(self.tableviewA)
        layout.addWidget(buttonResize)
        layout.addWidget(buttonZoomIn)
        layout.addWidget(buttonZoomOut)

        self.setLayout(layout)

        # self.tableviewA.resizeRowsToContents()
        # self.tableviewA.resizeColumnsToContents()

    def zoomIn(self, arg):
        self.tablemodel.resizePixmap(1.1)
        self.resizeView()

    def zoomOut(self, arg):
        self.tablemodel.resizePixmap(0.9)
        self.resizeView()

    def resizeView(self):
        self.tableviewA.resizeRowsToContents()
        self.tableviewA.resizeColumnsToContents()       

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

Upvotes: 1

Related Questions