It is well possible to experiment with the problem of a dynamic widget on tables:
import dearpygui.dearpygui as dpg
from typing_extensions import Union, Optional, Any
# * Local Imports
import database
from units import __prog_name__, __prog_version__, __prog_author__
# ! Initializing
dpg.create_context()
# ! Functions
def start() -> None:
dpg.start_dearpygui()
dpg.destroy_context()
# ! Window Functions
def load_table(
sender: Optional[Union[int, str]],
app_data: Optional[Any],
table_name: str
):
print([sender, app_data, table_name])
if dpg.does_item_exist(f'{table_name}_table'):
dpg.delete_item(f'{table_name}_table')
with dpg.table(
tag=f'{table_name}_table',
resizable=True,
policy=dpg.mvTable_SizingStretchProp,
row_background=True,
borders_innerH=True,
borders_outerH=True,
borders_innerV=True,
borders_outerV=True
):
column_names = [column.name for column in database.metadata.tables[table_name].columns.values()]
for column_name in column_names:
dpg.add_table_column(label=column_name)
result = database.connection.execute(database.sqla.text(f"SELECT * FROM '{table_name}';"))
for row in result:
with dpg.table_row():
for value in row:
dpg.add_text(str(value))
# ! Main Window
with dpg.window(tag="hippodrome_app"):
with dpg.tab_bar(label="Hippodrome Tabs"):
with dpg.tab(label="Horses"):
load_table(None, None, 'Horses')
dpg.add_button(label="Update", callback=(lambda sender, app_data: load_table(sender, app_data, 'Horses')))
with dpg.tab(label="Jockeys"):
load_table(None, None, 'Jockeys')
dpg.add_button(label="Update", callback=(lambda sender, app_data: load_table(sender, app_data, 'Jockeys')))
with dpg.tab(label="Races"):
load_table(None, None, 'Races')
dpg.add_button(label="Update", callback=(lambda sender, app_data: load_table(sender, app_data, 'Races')))
# ! Settings
dpg.create_viewport(title=f'{__prog_name__} v{__prog_version__}', width=800, height=350)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("hippodrome_app", True)
# ! Start
if __name__ == "__main__":
start()
At the first start of the program, the tables are loaded normally and without problems. But when you click on the Update button, an error is displayed:
Exception:
Error: [1011]
Command: add_*
Item: 104
Label:
Item Type: mvAppItemType::mvTable
Message: Parent could not be deduced.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Romanin\AppData\Local\Programs\Python\Python312\Lib\site-packages\dearpygui\dearpygui.py", line 2601, in table
widget = internal_dpg.add_table(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, width=width, height=height, indent=indent, parent=parent, before=before, source=source, callback=callback, show=show, pos=pos, filter_key=filter_key, delay_search=delay_search, header_row=header_row, clipper=clipper, inner_width=inner_width, policy=policy, freeze_rows=freeze_rows, freeze_columns=freeze_columns, sort_multi=sort_multi, sort_tristate=sort_tristate, resizable=resizable, reorderable=reorderable, hideable=hideable, sortable=sortable, context_menu_in_body=context_menu_in_body, row_background=row_background, borders_innerH=borders_innerH, borders_outerH=borders_outerH, borders_innerV=borders_innerV, borders_outerV=borders_outerV, no_host_extendX=no_host_extendX, no_host_extendY=no_host_extendY, no_keep_columns_visible=no_keep_columns_visible, precise_widths=precise_widths, no_clip=no_clip, pad_outerX=pad_outerX, no_pad_outerX=no_pad_outerX, no_pad_innerX=no_pad_innerX, scrollX=scrollX, scrollY=scrollY, no_saved_settings=no_saved_settings, **kwargs)
SystemError: <built-in function add_table> returned a result with an exception set
During handling of the above exception, another exception occurred:
Exception: Error: [1009] Message: No container to pop.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "D:\Users\Romanin\Desktop\Hippodrome\app.py", line 48, in <lambda>
dpg.add_button(label="Update", callback=(lambda sender, app_data: load_table(sender, app_data, 'Horses')))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Users\Romanin\Desktop\Hippodrome\app.py", line 24, in load_table
with dpg.table(
File "C:\Users\Romanin\AppData\Local\Programs\Python\Python312\Lib\contextlib.py", line 137, in __enter__
return next(self.gen)
^^^^^^^^^^^^^^
File "C:\Users\Romanin\AppData\Local\Programs\Python\Python312\Lib\site-packages\dearpygui\dearpygui.py", line 2605, in table
internal_dpg.pop_container_stack()
SystemError: <built-in function pop_container_stack> returned a result with an exception set
I understand why this is happening, for the first time the context manager, which is called in the method load_table(...)
, opens inside the context manager dpg.tab(label="...")
, but by the time the application opens, this context manager closes.
How do I COMPLETELY update the table (widget)?
I tried not to delete the table, but to delete only its child widgets, because at that time I did not understand what the problem was:
dpg.delete_item(f'{table_name}_table', children_only=True)
I sat for a couple more hours, and I came across this option.
You need to specify the tag
argument for the table, for the button that comes after the table and for the parent widget.
Then, in the table, pass parent
(the tag of the parent widget) and before
(the widget in front of which the table will be located) as arguments.
import dearpygui.dearpygui as dpg
from typing_extensions import Union, Optional, Any
# * Local Imports
import database
# ! Initializing
dpg.create_context()
# ! Functions
def start() -> None:
dpg.start_dearpygui()
dpg.destroy_context()
# ! Window Functions
def load_table(
sender: Optional[Union[int, str]],
app_data: Optional[Any],
table_name: str
):
print([sender, app_data, table_name])
if dpg.does_item_exist(f'{table_name}_table'):
dpg.delete_item(f'{table_name}_table')
with dpg.table(
tag=f'{table_name}_table',
resizable=True,
policy=dpg.mvTable_SizingStretchProp,
row_background=True,
borders_innerH=True,
borders_outerH=True,
borders_innerV=True,
borders_outerV=True,
parent=f"{table_name}_table_tab",
before=f"{table_name}_table_update_button"
):
column_names = [column.name for column in database.metadata.tables[table_name].columns.values()]
for column_name in column_names:
dpg.add_table_column(label=column_name)
result = database.connection.execute(database.sqla.text(f"SELECT * FROM '{table_name}';"))
for row in result:
with dpg.table_row():
for value in row:
dpg.add_text(str(value))
dpg.add_button(
label="Update",
tag=f"{table_name}_table_update_button",
callback=(lambda sender, app_data: load_table(sender, app_data, 'Races'))
)
# ! Main Window
with dpg.window(tag="hippodrome_app"):
with dpg.tab_bar(label="Hippodrome Tabs"):
with dpg.tab(label="Horses", tag="Horses_table_tab"):
load_table(None, None, 'Horses')
with dpg.tab(label="Jockeys", tag="Jockeys_table_tab"):
load_table(None, None, 'Jockeys')
with dpg.tab(label="Races", tag="Races_table_tab"):
load_table(None, None, 'Races')
# ! Settings
dpg.create_viewport(title=f'Dinamic Widgets', width=800, height=350)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("hippodrome_app", True)
# ! Start
if __name__ == "__main__":
start()