PyQGIS – Setting Permanent Minimum Height and Width for Cells in Attribute Table

attribute-tabledimensionsfields-attributespyqgiswidth

Let's assume there is an attribute table of a vector layer which was opened with F6, see image below

input

With the code below I could set the minimum height and width of all cells in the attribute table.

from PyQt5.QtWidgets import QApplication, QTableView

attrTables = [d for d in QApplication.instance().allWidgets() if 'QgsAttributeTableDialog' in d.objectName()]

if len(attrTables):
    attrTables[0].findChildren(QTableView)[0].resizeColumnsToContents()
    attrTables[0].findChildren(QTableView)[0].resizeRowsToContents()

result_temp

However it is only temporal. After closing and opening the table, the height of each cell does not remain, only the width is maintained.

result_current

How can I make it permanent in height?


References:

Best Answer

Conclusion

  • It is impossible to apply permanent changes to cells' height. It seems like resizeRowsToContents() works only partially. Because after closing the attribute table, rows won't preserve their dimension
  • It is possible to adjust column width both via PyQt and PyQGIS

Indeed, as was mentioned in a comment by @Matt, there is a setAttributeTableConfig() method of the QgsVectorLayer class:

This is a container for configuration of the attribute table.

The configuration is specific for one vector layer.

To get the width of a column one can try the attributeTableConfig() method.

Returns the attribute table configuration object.

This defines the appearance of the attribute table.

from qgis.utils import iface 

layer = iface.activeLayer()

layer_attr_table_config = layer.attributeTableConfig()
columns = layer_attr_table_config.columns()

for column in columns:
    if not column.hidden:
        print(f"Column '{column.name}' : {column.width}")

Nevertheless, it will show the default width which is -1.

Column 'osm_id' : -1
Column 'lastchange' : -1
Column 'code' : -1
Column 'fclass' : -1
Column 'geomtype' : -1
Column 'name' : -1
Column 'type' : -1
Column 'height' : -1
Column 'levels' : -1

More details can be found in QgsAttributeTableConfig class.

To change the width of a single column

It utilizes the setColumnWidth() and setAttributeTableConfig() methods

from qgis.core import QgsProject

def setting_one_column_width(layer_name: str, column_name: str, new_width: int):
    """
    Changes the width of a single column in the layer
    :param layer_name: name of the layer
    :param column_name: name of the target column
    :param new_width: new column width in pixels
    """
    
    layer = QgsProject.instance().mapLayersByName(layer_name)[0]
    column_index = layer.fields().indexOf(column_name)

    layer_attr_table_config = layer.attributeTableConfig()
    layer_attr_table_config.setColumnWidth(column_index, new_width)
    
    layer.setAttributeTableConfig(layer_attr_table_config)

    return

setting_one_column_width('gis_osm_buildings', 'osm_id', 100)

To change the width of all columns

Based on @ThomasG77's answer. It uses the setColumns() and setAttributeTableConfig() methods

from qgis.core import QgsAttributeTableConfig, QgsProject

def setting_all_columns_widths(layer_name: str, new_width: int) -> None:
    """
    Changes widths of all columns in the layer
    :param layer_name: name of the layer
    :param new_width: new column width in pixels
    """
    
    layer = QgsProject.instance().mapLayersByName(layer_name)[0]

    layer_attr_table_config = layer.attributeTableConfig()
    columns_config = layer_attr_table_config.columns()

    new_columns_config = []
    new_layer_attr_table_config = QgsAttributeTableConfig()

    for column in columns_config:
        new_column = layer_attr_table_config.ColumnConfig()
        new_column.hidden = column.hidden
        new_column.name = column.name
        new_column.type = column.type
        new_column.width = new_width
        new_columns_config.append(new_column)

    new_layer_attr_table_config.setColumns(new_columns_config)

    layer.setAttributeTableConfig(new_layer_attr_table_config)

    return

setting_all_columns_widths('gis_osm_buildings', 100)

Keep in mind, that changes will be noticeable after closing and opening again the attribute table.

However, there are also several incompleteness in the above approaches:

  1. autosize functionality comes from PyQt
  2. it does not shrink rows, only columns

To autosize the width of all columns

Partially overlaps with @Joseph's and @MatthiasKuhn's answers. It applies the resizeColumnsToContents() method from the QTableView class.

from qgis.utils import iface
from qgis.core import QgsProject
from PyQt5.QtWidgets import QApplication, QTableView

def autosize_all_columns_widths(layer_name: str) -> None:
    """
    Autosizes widths of all columns in the layer
    :param layer_name: name of the layer
    """

    layer = QgsProject.instance().mapLayersByName(layer_name)[0]

    all_widgets = QApplication.instance().allWidgets()
    attribute_table_widgets = [widget for widget in all_widgets if "AttributeTable" in widget.objectName()]

    if len(attribute_table_widgets) == 0:
        iface.showAttributeTable(layer)
        all_widgets = QApplication.instance().allWidgets()
        attribute_table_widgets = [widget for widget in all_widgets if "AttributeTable" in widget.objectName()]

    for widget in attribute_table_widgets:
        if not widget.isWindow():
            if layer.name() in widget.objectName():
                table_view = widget.findChildren(QTableView)[0]
                table_view.resizeColumnsToContents()
                # table_view.resizeRowsToContents()
                widget.close()

    return

autosize_all_columns_widths('gis_osm_buildings')

References: