hoffstadt / hoffstadt/DearPyGui
Stage container looses its children when applying >= 10 of them only if you use same stage container multiple times.
- Dominant language
- C++
- Stars
- 15.6k
- Forks
- 783
- PR merge metrics
- No merged PRs in 30d
Description
## Version of Dear PyGui
Version: 1.1.3
Operating System: Windows 10
## My Issue/Question
Hi, I modelled on @hoffstadt code of [Simple Tables](https://github.com/hoffstadt/DearPyGui_Ext/blob/master/dearpygui_ext/simple_table.py) in dearpygui_ext. I wanted to achieve table autogeneration and pagination(prepare next view in stage container and marry everything with pydantic) and found this bug(?).
Stage container looses its children when applying >= 10 of them. In my example on 3rd stage container reuse with spawning 10 children, children are lost.
By reusing stage container i mean ```dpg.delete_item(item=rows_stage_id, children_only=True)```
@hoffstadt code is not reusing same stage container- its being deleted after table creation.
It might not be a bug because I'm just guessing what ```dpg.configure_app(skip_positional_args=True, skip_required_args=True)``` mean and it's possible I have used it in wrong way or I have used stage container in wrong way.
But currently I think its a bug.
## To Reproduce
Steps to reproduce the behavior:
1. Run example
2. Click 'Run' button to trigger loop.
3. After 3rd time of reusing stage container it looses its children when there are 10 children. The moment of loss is not consistent for me. 99% of time stage looses children while spawning children in it because of error on
```assert curr_no_of_rows_in_stage_container == requested_no_of_rows``` but i got 2 times assertion error on table with
```assert curr_no_of_rows_in_table_container == requested_no_of_rows``` which indicates loosing children while doing ```unstage()```
4. Change var ```check = False``` then you can see that only 3rd time of stage reuse makes stage loose its children.
5. Turn back on assertion with ```check = True```and change ```requested_no_of_rows``` in ```callback``` function to f.e. 3 and there will never appear any assertion error. Compare no. of children: 3(in my case no loose) ; 10(in my case loose on 3rd reuse) ; 200 (in my case loose on 9th reuse)
## Expected behavior
Stage container wont loose its children.
## Screenshots/Video
pass
## Standalone, minimal, complete and verifiable example
Example creates table and assigns ids for table and stage.
Clicking "Run" button runs ```callback``` function which in loop:
1. prepares rows in stage.
2. After spawning rows in stage, function ```render_prepared_data``` is called to delete current table rows and unstage the stage with new rows.
```python
import dearpygui.dearpygui as dpg
import time
def render_prepared_data(table_id: int, rows_stage_id: int):
"""
function to delete current table children in slot=1 (rows) and assign new children to table using prepared ones in stage container.
dpg.mutex() used to make everything happen in 1 frame.
:param table_id:
:param rows_stage_id:
"""
with dpg.mutex():
dpg.delete_item(item=table_id, children_only=True, slot=1)
dpg.push_container_stack(item=table_id)
dpg.unstage(item=rows_stage_id)
dpg.pop_container_stack()
def callback(table_id: int, rows_stage_id: int):
"""
callback for "Run" button.
Creates new rows in stage container. Stage container is 'reused' every loop by clearing its children.
After that render_prepared_data() is called.
Bug: When there are >= 10 of children, container looses its children.
There are no assertion errors when there are <1;9> children.
More children = more available container reusages with no children loosing.
Compare no. of children: 3(in my case no loose) ; 10(in my case loose on 3rd reuse) ; 200 (in my case loose on 9th reuse)
:var requested_no_of_rows: how many rows have to be created. assertion breaks when >= 10 (bug?)
:var check: run assert functions. Checks number of rows in table and in stage container. Checks if python table_row code has been called
:var job_done: is used to assert that loop called function creating rows.
:var curr_no_of_rows_in_stage_container: is used to assert that there is proper number of rows in stage
:var curr_no_of_rows_in_table_container: is used to assert that there is proper number of rows in stage
:param table_id:
:param rows_stage_id:
"""
requested_no_of_rows = 10 # <------ CHANGE THIS <10 for no assertion errors.
check = False # <------ CHANGE THIS to False for no assertion checks
loop_cnt = 0
while True:
loop_cnt += 1
if dpg.does_item_exist(item=rows_stage_id):
dpg.delete_item(item=rows_stage_id, children_only=True)
job_done = False
with dpg.mutex():
with dpg.stage(tag=rows_stage_id) as stage_id:
dpg.configure_app(skip_positional_args=True, skip_required_args=True)
for row_no in range(0, requested_no_of_rows):
job_done = True
with dpg.table_row():
a = dpg.add_text()
b = dpg.add_text()
dpg.set_value(item=a, value='a')
dpg.set_value(item=b, value='b')
dpg.configure_app(skip_positional_args=False, skip_required_args=False)
if check:
assert job_done is True
# check no of rows in stage container. There assertion breaks every 3rd time.
curr_no_of_rows_in_stage_container = len(dpg.get_item_info(item=rows_stage_id)['children'][1])
print(f'\rLoop no.: {loop_cnt} | stage: {curr_no_of_rows_in_stage_container}', end='')
if check:
assert curr_no_of_rows_in_stage_container == requested_no_of_rows
render_prepared_data(table_id=table_id, rows_stage_id=rows_stage_id) # clear table slot=1 and unstage stage with rows.
curr_no_of_rows_in_table_container = len(dpg.get_item_info(item=table_id)['children'][1])
if check:
assert curr_no_of_rows_in_table_container == len(dpg.get_item_info(item=table_id)['children'][1])
time.sleep(1)
dpg.create_context()
with dpg.window() as window_id:
table_id = dpg.generate_uuid()
rows_stage_id = dpg.generate_uuid()
dpg.add_button(label='Run', callback=lambda: callback(table_id=table_id, rows_stage_id=rows_stage_id))
with dpg.table(tag=table_id) as table_id:
dpg.add_table_column(label='A col')
dpg.add_table_column(label='B col')
dpg.create_viewport(title='stage looses its children when no of children >= 10', width=800, height=800)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window(window=window_id, value=True)
dpg.start_dearpygui()
dpg.destroy_context()
```
Contributor guide
Assessment
This issue has not been assessed yet.