You can limit the size of the vertical header using setMaximWidth, and use setTextElideMode to adjust how the text is cropped.
However, there is no built-in method for making the vertical header width resizable by the user. So as a work-around, you could use the resize-event to adjust the width of the vertical header to a percentage of the total width. That way, resizing the window will also change the width of the vertical header.
Here is a demo script that implements all of that:
import sys
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self, rows, columns):
super(Window, self).__init__()
self.table = QtGui.QTableView(self)
self.table.installEventFilter(self)
self.table.verticalHeader().setTextElideMode(QtCore.Qt.ElideRight)
model = QtGui.QStandardItemModel(rows, columns, self.table)
for row in range(rows):
item = QtGui.QStandardItem('FOO_BAR_123_AB_CD_%s' % row)
model.setVerticalHeaderItem(row, item)
for column in range(columns):
item = QtGui.QStandardItem('(%d, %d)' % (row, column))
item.setTextAlignment(QtCore.Qt.AlignCenter)
model.setItem(row, column, item)
self.table.setModel(model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.table)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.Resize and source is self.table:
source.verticalHeader().setMaximumWidth(source.width() / 4)
return super(Window, self).eventFilter(source, event)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window(15, 5)
window.setGeometry(600, 100, 400, 300)
window.show()
sys.exit(app.exec_())
UPDATE:
I had a go at writing a custom header class that implements user resizing of the vertical header width. It almost works, but I cannot find a way to update the view properly whilst dragging with the mouse. Anyway, here is a demo of what I have so far in case anyone can see how to make it work:
import sys
from PyQt4 import QtCore, QtGui
class HeaderView(QtGui.QHeaderView):
def __init__(self, table):
super(HeaderView, self).__init__(QtCore.Qt.Horizontal, table)
self.setClickable(True)
self.setHighlightSections(True)
self.setResizeMode(QtGui.QHeaderView.Interactive)
self._vheader = table.verticalHeader()
self._resizing = False
self._start_position = -1
self._start_width = -1
def mouseMoveEvent(self, event):
if self._resizing:
width = event.x() - self._start_position + self._start_width
if width > 0:
self._vheader.setFixedWidth(width)
# TODO: find a proper replacement for this
self.geometriesChanged.emit()
else:
super(HeaderView, self).mouseMoveEvent(event)
if 0 <= event.x() <= 3:
if not self.testAttribute(QtCore.Qt.WA_SetCursor):
self.setCursor(QtCore.Qt.SplitHCursor)
def mousePressEvent(self, event):
if not self._resizing and event.button() == QtCore.Qt.LeftButton:
if 0 <= event.x() <= 3:
self._start_position = event.x()
self._start_width = self._vheader.width()
self._resizing = True
return
super(HeaderView, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
self._resizing = False
super(HeaderView, self).mouseReleaseEvent(event)
class Window(QtGui.QWidget):
def __init__(self, rows, columns):
super(Window, self).__init__()
self.table = QtGui.QTableView(self)
self.table.setHorizontalHeader(HeaderView(self.table))
self.table.verticalHeader().setTextElideMode(QtCore.Qt.ElideRight)
model = QtGui.QStandardItemModel(rows, columns, self.table)
for row in range(rows):
item = QtGui.QStandardItem('FOO_BAR_123_AB_CD_%s' % row)
item.setToolTip(item.text())
model.setVerticalHeaderItem(row, item)
for column in range(columns):
item = QtGui.QStandardItem('(%d, %d)' % (row, column))
item.setTextAlignment(QtCore.Qt.AlignCenter)
model.setItem(row, column, item)
self.table.setModel(model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.table)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window(15, 5)
window.setGeometry(600, 100, 400, 300)
window.show()
sys.exit(app.exec_())