hoffstadt / DearPyGui

Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies
https://dearpygui.readthedocs.io/en/latest/
MIT License
12.69k stars 669 forks source link

Tree nodes and collapsing headers close when the viewport is minimised #1873

Closed my1e5 closed 6 months ago

my1e5 commented 1 year ago

If I have a tree node or collapsing header inside a child window they become closed when I minimise then maximise the viewport.

Code

import dearpygui.dearpygui as dpg
dpg.create_context()

with dpg.window(width=300, height=300):
    with dpg.tree_node(label="A", default_open=True):
        dpg.add_text("Hello World")
    with dpg.collapsing_header(label="B",default_open=True):
        dpg.add_text("Hello World")
    with dpg.child_window():
        with dpg.tree_node(label="C", default_open=True):
            dpg.add_text("Hello World")
        with dpg.collapsing_header(label="D",default_open=True):
            dpg.add_text("Hello World")

dpg.create_viewport()
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

Before minimising the viewport image

Minimising the viewport like this image

After re-opening the viewport image

Notice how the child window tree node and collapsing header have closed. I'm running DPG 1.6.2 and Windows 10

sedenka commented 1 year ago

I can confirm this (I have also 1.6.2/W10). Note that when the tree_node forms a more complex hierarchy, only the top level gets closed, lower levels remain opened.

sedenka commented 1 year ago

I have found a modification of the source code which might fix this issue. But basically I do not know what I am doing so be very careful if you are going to use it (or wait for proper fix from the devs).

For v1.6.2: Find method draw() in src\ui\AppItems\containers\mvTreeNode.cpp and src\ui\AppItems\containers\mvCollapsingHeader.cpp. Inside, look for ImGui::SetNextItemOpen(*_value). This function is called with only one argument but it has actually two arguments, where the second one is being filled with default value equal to ImGuiCond_None or ImGuiCond_Always.

For current master (1.6.3): I did not try it with this version but it looks like the draw() methods have been moved to DearPyGui::draw_tree_node() and DearPyGui::draw_collapsing_header() in the src/mvContainers.cpp.

I have "fixed" it by adding second argument equal to ImGuiCond_Appearing:

ImGui::SetNextItemOpen(*_value, ImGuiCond_Appearing);

.... but it looks like ImGuiCond_Once or ImGuiCond_FirstUseEver will fix it too. Note that I am totally unaware of the consequences of this change. If nothing else, it could help the devs to find proper solution sooner.

my1e5 commented 6 months ago

This bug is still present in 1.10.1

v-ein commented 6 months ago

This is what's causing the problem:

bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)
{
    ImGuiWindow* window = GetCurrentWindow();
    if (window->SkipItems)
        return false;

As soon as the window gets out of sight, TreeNodeEx returns false as if the node was collapsed, and that gets stored in the node's config.value. Instead of minimizing the viewport, you can drag the window beyond viewport boundaries so that child_window gets completely outside the viewport - the result will be the same.

v-ein commented 6 months ago

Here's a bit better test:

import dearpygui.dearpygui as dpg
dpg.create_context()

with dpg.window(width=300, height=300) as wnd:
    def set_state(sender, checked: bool):
        for i in range(500, 504):
            dpg.set_value(i, checked)

    dpg.add_checkbox(label="Open", callback=set_state)

    with dpg.tree_node(label="A", tag=500):
        dpg.add_text("Hello World")
    with dpg.collapsing_header(label="B",tag=501):
        dpg.add_text("Hello World")
    with dpg.child_window():
        with dpg.tree_node(label="C", tag=502):
            dpg.add_text("Hello World")
        with dpg.collapsing_header(label="D",tag=503):
            dpg.add_text("Hello World")

dpg.create_viewport(width=500, height=500)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

Here, you can programmatically expand or collapse all tree nodes and headers by clicking on the Open checkbox. Open all nodes and then resize the window so that the child window is completely hidden (outside the parent window boundaries), then resize it back to normal.