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.62k stars 669 forks source link

The popup appears in the wrong place on first use #1691

Open L-Nafaryus opened 2 years ago

L-Nafaryus commented 2 years ago

Version of Dear PyGui

Version: 1.5.1 Operating System: Manjaro Linux (x86_64)

My Issue/Question

The popup appears in the corner of the primary window (pos [0, 0]) and expands (width = -1 argument for the child button) on first use.

To Reproduce

Steps to reproduce the behavior:

  1. Right click on the tab.
  2. See unexpected position and size.
  3. Click somewhere to close popup.
  4. Right click on the tab again.
  5. See expected position and size.

Expected behavior

The popup should appear under the mouse position from the tab widget's hitbox with the correct size on every use.

Screenshots/Video

popup from tab

Standalone, minimal, complete and verifiable example

import dearpygui.dearpygui as dpg

dpg.create_context()

with dpg.window(tag = "Primary") as primary:
    with dpg.child_window(tag = "Test", border = False):
        with dpg.tab_bar(label = "tabbar"):
            # First tab
            with dpg.tab(label = "tab1", tag = "tab1"):
                with dpg.popup(dpg.last_item(), mousebutton = dpg.mvMouseButton_Right):
                    dpg.add_button(label = "close", width = -1, callback = lambda: dpg.delete_item("tab1"))
                dpg.add_text("Tab!")
            # Second tab without width = -1 argument for the child button
            with dpg.tab(label = "tab2", tag = "tab2", show = True):
                with dpg.popup(dpg.last_item(), mousebutton = dpg.mvMouseButton_Right):
                    dpg.add_button(label = "close", callback = lambda: dpg.delete_item("tab2"))
                dpg.add_text("Tab 2!")

dpg.create_viewport(title = "New GUI", width = 1000, height = 800)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("Primary", True)
dpg.start_dearpygui()
dpg.destroy_context()
hugle commented 1 year ago

I think it is because of popup window does not know where the pos of tab1 or tab2 is. If the frame is rendered one time. A correct popup position can be shown.

Check the dirty rendering code below for troubleshoot:

import dearpygui.dearpygui as dpg

dpg.create_context()

def call_me(s, a, u):
    print("call me")

with dpg.window(tag = "Primary") as primary:
    with dpg.child_window(tag = "Test", border = False):
        with dpg.tab_bar(label = "tabbar"):
            # First tab
            with dpg.tab(label = "tab1", tag = "tab1"):
                dpg.add_text("Tab!", tag="test")

dpg.create_viewport(title = "New GUI", width = 1000, height = 800)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("Primary", True)

#dpg.start_dearpygui()

count = 1

while dpg.is_dearpygui_running():
    dpg.render_dearpygui_frame()

    if count == 1:
        with dpg.popup("tab1", mousebutton = dpg.mvMouseButton_Right):
            dpg.add_button(label = "close", width = -1, callback = call_me)

        count += 1

dpg.destroy_context()
hugle commented 1 year ago

I also found if you place the pop up code after set_primary_window, you can also get correct pop up pos for first time:

import dearpygui.dearpygui as dpg

dpg.create_context()

with dpg.window(tag = "Primary") as primary:
    with dpg.child_window(tag = "Test", border = False):
        with dpg.tab_bar(label = "tabbar"):
            # First tab
            with dpg.tab(label = "tab1", tag = "tab1"):
                dpg.add_text("Tab!")
            # Second tab without width = -1 argument for the child button
            with dpg.tab(label = "tab2", tag = "tab2", show = True):
                dpg.add_text("Tab 2!")

dpg.create_viewport(title = "New GUI", width = 1000, height = 800)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("Primary", True)

with dpg.popup("tab1", mousebutton = dpg.mvMouseButton_Right):
    dpg.add_button(label = "close", width = -1, callback = lambda: dpg.delete_item("tab1"))

with dpg.popup("tab2", mousebutton = dpg.mvMouseButton_Right):
    dpg.add_button(label = "close", callback = lambda: dpg.delete_item("tab2"))

dpg.start_dearpygui()
dpg.destroy_context()
my1e5 commented 1 year ago

I'm also having this issue - using DPG 1.7.3. It seems to only happen to items+popups that were created before the app launches (i.e. created before dpg.start_dearpygui() is called).

v-ein commented 4 months ago

Looks like it's something in set_primary_window that affects the popup position. Doesn't occur without set_primary_window; and, as @hugle mentioned, doesn't occur if popup is created after set_primary_window (but still before start_dearpygui).

v-ein commented 4 months ago

Look ma!

static PyObject*
set_primary_window(PyObject* self, PyObject* args, PyObject* kwargs)
{

<...>

    // reset other windows
    for (auto& window : GContext->itemRegistry->windowRoots)
    {
        if (window->uuid != item)
        {
            <...>

            window->info.dirtyPos = true;
        }
    }

set_primary_window certainly needs a bit of a redesign. Setting the "dirty pos" flag on a popup is exactly what makes that popup picking up the (0, 0) position on its first appearance (see #1975 and the corresponding fix).