I want to dock at the right the attribute table of layer "Constantes" in QGIS 3.30. I found resources and tried this code :
layer_name = "Constantes"
layers = QgsProject.instance().mapLayersByName(layer_name)
if len(layers) == 1:
layer = layers[0]
attr_table = iface.showAttributeTable(layer)
widgets = QApplication.instance().allWidgets()
attrTables = [t for t in widgets if t.objectName() == u'AttributeTable']
for table in attrTables:
iface.addDockWidget(Qt.LeftDockWidgetArea, table)
The attribute table displays in a new window but not docked. attrTables is empty that's why it does not work.
Is there a way to correct the code ?
2 Answers 2
Soon before your answer, I find other way (maybe not very clean but it worked) :
QSettings().setValue("/Qgis/dockAttributeTable", True)
layer_name = "Constantes"
layers = QgsProject.instance().mapLayersByName(layer_name)
if len(layers) == 1:
layer = layers[0]
iface.showAttributeTable(layer)
for dock in iface.mainWindow().findChildren(QDockWidget):
if layer_name in dock.windowTitle():
iface.addDockWidget(Qt.LeftDockWidgetArea, dock)
-
I'm glad you were able to solve it. I would argue that it is indeed a cleaner version of my second method. It's nice to learn of the dockAttributeTable setting.Matt– Matt2025年01月03日 20:43:13 +00:00Commented Jan 3 at 20:43
You can get a reference to the open attribute table's container by using attr_table.parent()
. However, the problem you will consequently face is that the container is not a QgsDockWidget
(it is a QDialog
) and you will not be able to dock it. This can be demonstrated by attempting to dock the attribute table manually by dragging it over a dockable area.
What you can do is create a new QgsDockWidget
and place the attribute table inside it. This can then be docked in the way you attempted.
layer_name = 'Constantes'
layers = QgsProject.instance().mapLayersByName(layer_name)
if len(layers) == 1:
layer = layers[0]
attr_table = iface.showAttributeTable(layer)
# create a new QgsDockWidget and set its title to be the layer name
dock_widget = QgsDockWidget(layer.name())
# assign the attribute table to the dockwidget (via its parent)
dock_widget.setWidget(attr_table.parent())
# dock the widget
iface.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)
Note: this method will cause undesirable behaviour if the Dock attribute table action in the attribute table is clicked after docking it this way (a new QgsDockWidget
will be created and the attribute table will move into it, leaving the empty dockwidget still visible in the Qt.LeftDockWidgetArea
).
Alternative method
This method first docks the attribute table by programmatically clicking the Dock Attribute Table action and then shifting the automatically generated QgsDockWidget
to the desired area.
The advantage is that the the action button is then toggled on when the attribute table is docked. Clicking the action button will undock the attribute table as intended.
layer_name = 'Constantes'
layers = QgsProject.instance().mapLayersByName(layer_name)
if len(layers) == 1:
layer = layers[0]
attr_table = iface.showAttributeTable(layer)
widgets = QApplication.instance().allWidgets()
# get a list of children of the attribute table
# this includes the action buttons
attribute_table_children = attr_table.children()
# get a reference to the 'Dock Attribute Table' action
dock_action = [child for child in attribute_table_children if hasattr(child, 'toolTip') and child.toolTip() == 'Dock Attribute Table'][0]
# trigger the 'Dock Attribute Table' action
dock_action.trigger()
# get a reference to the parent of the attribute table which is now a QgsDockWidget
dock_widget = attr_table.parent()
# dock the attribute table
iface.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)