Search code examples
pythonpyside6

How to set a PySide6 QTableWidget column width to 15pt?


I'd like to create a small table widget with buttons in column #2. The buttons are thin (15pt) as they only contain a T.

Here is a small working example.

import sys
from PySide6.QtWidgets import (
    QMainWindow, QApplication, QTableWidget, QLabel, QPushButton
)
from PySide6.QtCore import Qt

class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("My App")

        Nrows, Ncols = 5, 3
        table = QTableWidget(Nrows, Ncols, self)

        for col in [0, 2]:
            for row in range(Nrows):
                table.setCellWidget(row, col,
                    QLabel(f"row {row} column {col}")
                )
        for row in range(Nrows):
            push = QPushButton("T")
            push.setFixedWidth(15)
            table.setCellWidget(row, 1,push)

        self.setCentralWidget(table)

app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

This produces the following window.

enter image description here

The problem is that I want the push button column to be 15pt with at startup too. So that the column width is the same width as the push button.

The two problems are:

  1. I need to resize at startup
  2. Resizing does not goes down to 15pt. It seems the column width can not be under approx. 20pt.

enter image description here

How can this be resolved?


Solution

  • The default minimum section size is computed by the current style and font.

    You can override the size of a section by using setColumnWidth():

    table.setColumnWidth(1, 15)
    

    Which is the same as using resizeSection of the header:

    table.horizontalHeader().resizeSection(1, 15)
    

    But you should also ensure that the minimum section is set, otherwise if the user tries to resize the section, it will fall back to the default minimum:

    table.horizontalHeader().setMinimumSectionSize(15)
    

    Note that you can also use the setSectionResizeMode() (but you still must set the minimum section size):

    table.horizontalHeader().setMinimumSectionSize(15)
    table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
    

    Note that a button width of 15 is really too narrow, and you cannot rely on your computer font: other users might have different styles (which add bigger margins between text and button borders) or fonts bigger than yours; you should ensure that the minimum width is based on the font and style, and also always provide the possibility to adjust the size:

    width = (
        self.fontMetrics().horizontalAdvance("T")
        + self.style().pixelMetric(QStyle.PM_ButtonMargin) * 2
        + self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) * 2
    )
    
    for row in range(Nrows):
        push = QPushButton("T")
        push.setMinimumWidth(width) # set a *minimum* width, not a fixed one
        table.setCellWidget(row, 1, push)
    table.horizontalHeader().setMinimumSectionSize(width)
    table.setColumnWidth(1, width)