2

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:

3
  • 1
    Have you seen the setAttributeTableConfig() method of QgsVectorLayer? Perhaps this is the way to go. Unfortunately, I don't have time to look into it properly right now.
    – Matt
    Commented May 20, 2022 at 12:32
  • Thank you for a hint!
    – Taras
    Commented May 20, 2022 at 12:32
  • 1
    My other suggestion would be to attach your current code to the signal that is fired when an attribute table is opened. I can't easily see which signal that is though.
    – Matt
    Commented May 20, 2022 at 12:35

1 Answer 1

1

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:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.