I really like a clean result of self-adjusting to the QTableView
's width of the columns using:
self.view.horizontalHeader().setResizeMode(QHeaderView.Stretch)
But unfortunately with this flag used the columns width doesn't stay adjustable any longer (the user is not able to resize the columns width).
I wonder if there is an alternative way to set the columns width to the width of the QTableView
and yet keeping the columns width "user-adjustable"?
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class Model(QAbstractTableModel):
def __init__(self, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.items = ['Item_A_001','Item_A_002','Item_B_001','Item_B_002']
self.totalColumn=10
def rowCount(self, parent=QModelIndex()):
return len(self.items)
def columnCount(self, parent=QModelIndex()):
return self.totalColumn
def setColumnCount(self, number):
self.totalColumn=number
self.reset()
def data(self, index, role):
if not index.isValid(): return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
row=index.row()
if row<len(self.items):
return QVariant(self.items[row])
else:
return QVariant()
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
tableModel=Model(self)
self.view=QTableView(self)
self.view.setModel(tableModel)
self.view.horizontalHeader().setResizeMode(QHeaderView.Stretch)
hideButton=QPushButton('Hide Column')
hideButton.clicked.connect(self.hideColumn)
unhideButton=QPushButton('Unhide Column')
unhideButton.clicked.connect(self.unhideColumn)
layout = QVBoxLayout(self)
layout.addWidget(self.view)
layout.addWidget(hideButton)
layout.addWidget(unhideButton)
self.setLayout(layout)
def hideColumn(self):
self.view.model().setColumnCount(1)
def unhideColumn(self):
self.view.model().setColumnCount(10)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
so here is a little trick I came up with. I modified the resize event of MyWindow to resize your QTableWidget.
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
self.tableModel=Model(self) #Set the model as part of your class to access it in the event handler
self.view=QTableView(self)
self.view.setModel(self.tableModel) #Modified here too
self.view.horizontalHeader().setResizeMode(QHeaderView.Interactive) #Mode set to Interactive to allow resizing
hideButton=QPushButton('Hide Column')
hideButton.clicked.connect(self.hideColumn)
unhideButton=QPushButton('Unhide Column')
unhideButton.clicked.connect(self.unhideColumn)
layout = QVBoxLayout(self)
layout.addWidget(self.view)
layout.addWidget(hideButton)
layout.addWidget(unhideButton)
self.setLayout(layout)
def hideColumn(self):
self.view.model().setColumnCount(1)
def unhideColumn(self):
self.view.model().setColumnCount(10)
#Added a reimplementation of the resize event
def resizeEvent(self, event):
tableSize = self.view.width() #Retrieves your QTableView width
sideHeaderWidth = self.view.verticalHeader().width() #Retrieves the left header width
tableSize -= sideHeaderWidth #Perform a substraction to only keep all the columns width
numberOfColumns = self.tableModel.columnCount() #Retrieves the number of columns
for columnNum in range( self.tableModel.columnCount()): #For each column
self.view.setColumnWidth(columnNum, int(tableSize/numberOfColumns) ) #Set the width = tableSize / nbColumns
super(MyWindow, self).resizeEvent(event) #Restores the original behaviour of the resize event
The only downfall is that the scrollbar is flicking. I think this can be solved with some adjustment.
Update:
Get a cleaner look when resizing, no more flicking, disabled the scrollbar.
Modified initialization of the QTableView:
self.view=QTableView(self)
self.view.setModel(self.tableModel)
self.view.horizontalHeader().setResizeMode(QHeaderView.Interactive)
#Added these two lines
self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.view.horizontalHeader().setStretchLastSection(True)
Modified resizeEvent:
def resizeEvent(self, event):
super(MyWindow, self).resizeEvent(event)
tableSize = self.view.width()
sideHeaderWidth = self.view.verticalHeader().width()
tableSize -= sideHeaderWidth
numberOfColumns = self.tableModel.columnCount()
remainingWidth = tableSize % numberOfColumns
for columnNum in range( self.tableModel.columnCount()):
if remainingWidth > 0:
self.view.setColumnWidth(columnNum, int(tableSize/numberOfColumns) + 1 )
remainingWidth -= 1
else:
self.view.setColumnWidth(columnNum, int(tableSize/numberOfColumns) )