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

Global themes for disabled components not working #2068

Open virgileMaon opened 1 year ago

virgileMaon commented 1 year ago

Version of Dear PyGui

Version: 1.9.0 Operating System: All

My Issue/Question

Global themes for disabled components not working. Enabled text color takes effect (which is also incorrect).

Expected behavior

Input float text should be red.

Related

https://github.com/hoffstadt/DearPyGui/issues/1401

Standalone, minimal, complete and verifiable example

import dearpygui.dearpygui as dpg

dpg.create_context()
dpg.create_viewport()
dpg.setup_dearpygui()

with dpg.theme() as global_theme:

    with dpg.theme_component(dpg.mvInputFloat, enabled_state=True):
        dpg.add_theme_color(dpg.mvThemeCol_Text, (255, 0, 0), category=dpg.mvThemeCat_Core)

dpg.bind_theme(global_theme)

with dpg.window(label="tutorial"):
    dpg.add_input_float(label="Input float", enabled=False)
    dpg.add_input_int(label="Input int", enabled=False)

dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
marcost83 commented 1 year ago

shouldn't the enabled_state be False in order to apply the disabled theme? Anyway, it works for me with enabled_state = False as I understood from documentation

v-ein commented 1 year ago

@marcost83 is right: enabled_state should be False. This makes theme_component(dpg.mvInputFloat) work as expected; however, theme_component(dpg.mvAll) doesn't work:

import dearpygui.dearpygui as dpg

dpg.create_context()
dpg.create_viewport(width=600, height=600)
dpg.setup_dearpygui()

with dpg.theme() as global_theme:

    with dpg.theme_component(dpg.mvAll, enabled_state=False):
        dpg.add_theme_color(dpg.mvThemeCol_Text, (0, 0, 255), category=dpg.mvThemeCat_Core)

dpg.bind_theme(global_theme)

with dpg.window(label="tutorial"):
    dpg.add_input_float(label="Input float", enabled=False)
    dpg.add_input_int(label="Input int", enabled=False)
    dpg.add_button(label="Button", enabled=False)

dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

image

DPG 1.9.1 on Windows.

v-ein commented 1 year ago

Another issue is that disabled components do not get grayed out by default. ImGui uses TextDisabled color for that, but DPG seems to have a different approach with Text and enabled_state=False; however, with the current defaults (as of 1.9.1), disabled items retain pure white text color. Neither does dearpygui_ext.themes.create_theme_imgui_yyy set this up properly.

v-ein commented 1 year ago

A workaround for now would be to add something like this to your global theme:

# In 'for', list all the types you need
for comp_type in (dpg.mvMenuItem, dpg.mvButton, dpg.mvText):
    with dpg.theme_component(comp_type, enabled_state=False):
        dpg.add_theme_color(dpg.mvThemeCol_Text, (0.50 * 255, 0.50 * 255, 0.50 * 255, 1.00 * 255))

If you need to modify a theme created somewhere else (e.g. if you're using themes from DearPyGui_Ext), you can easily wrap it in a context manager like this:

@contextmanager
def dpg_widget(widget: Union[int, str]) -> Generator[Union[int, str], None, None]:
    try:
        dpg.push_container_stack(widget)
        yield widget
    finally:
        dpg.pop_container_stack()

<...>

my_global_theme = create_theme_imgui_light()

with dpg_widget(my_global_theme):
    with dpg.theme_component(...):
        # add the stuff you need
mef51 commented 11 months ago

Thank you for the workaround. I had a lot of components so I just listed them all from the documentation. Here it is for convenience.

# fix for disabled theme see DearPyGui/issues/2068
comps = [dpg.mvInputText, dpg.mvButton, dpg.mvRadioButton, dpg.mvTabBar, dpg.mvTab, dpg.mvImage, dpg.mvMenuBar, dpg.mvViewportMenuBar, dpg.mvMenu, dpg.mvMenuItem, dpg.mvChildWindow, dpg.mvGroup, dpg.mvDragFloatMulti, dpg.mvSliderFloat, dpg.mvSliderInt, dpg.mvFilterSet, dpg.mvDragFloat, dpg.mvDragInt, dpg.mvInputFloat, dpg.mvInputInt, dpg.mvColorEdit, dpg.mvClipper, dpg.mvColorPicker, dpg.mvTooltip, dpg.mvCollapsingHeader, dpg.mvSeparator, dpg.mvCheckbox, dpg.mvListbox, dpg.mvText, dpg.mvCombo, dpg.mvPlot, dpg.mvSimplePlot, dpg.mvDrawlist, dpg.mvWindowAppItem, dpg.mvSelectable, dpg.mvTreeNode, dpg.mvProgressBar, dpg.mvSpacer, dpg.mvImageButton, dpg.mvTimePicker, dpg.mvDatePicker, dpg.mvColorButton, dpg.mvFileDialog, dpg.mvTabButton, dpg.mvDrawNode, dpg.mvNodeEditor, dpg.mvNode, dpg.mvNodeAttribute, dpg.mvTable, dpg.mvTableColumn, dpg.mvTableRow]
for comp_type in comps:
    with dpg.theme_component(comp_type, enabled_state=False):
        dpg.add_theme_color(dpg.mvThemeCol_Text, (0.50 * 255, 0.50 * 255, 0.50 * 255, 1.00 * 255))

Disabled components also still appear clickable, such as buttons as mentioned in #1639 . You can use the same theme workaround to get most widgets to appear disabled on hover:

comps = [dpg.mvInputText, dpg.mvButton, dpg.mvRadioButton, dpg.mvTabBar, dpg.mvTab, dpg.mvImage, dpg.mvMenuBar, dpg.mvViewportMenuBar, dpg.mvMenu, dpg.mvMenuItem, dpg.mvChildWindow, dpg.mvGroup, dpg.mvDragFloatMulti, dpg.mvSliderFloat, dpg.mvSliderInt, dpg.mvFilterSet, dpg.mvDragFloat, dpg.mvDragInt, dpg.mvInputFloat, dpg.mvInputInt, dpg.mvColorEdit, dpg.mvClipper, dpg.mvColorPicker, dpg.mvTooltip, dpg.mvCollapsingHeader, dpg.mvSeparator, dpg.mvCheckbox, dpg.mvListbox, dpg.mvText, dpg.mvCombo, dpg.mvPlot, dpg.mvSimplePlot, dpg.mvDrawlist, dpg.mvWindowAppItem, dpg.mvSelectable, dpg.mvTreeNode, dpg.mvProgressBar, dpg.mvSpacer, dpg.mvImageButton, dpg.mvTimePicker, dpg.mvDatePicker, dpg.mvColorButton, dpg.mvFileDialog, dpg.mvTabButton, dpg.mvDrawNode, dpg.mvNodeEditor, dpg.mvNode, dpg.mvNodeAttribute, dpg.mvTable, dpg.mvTableColumn, dpg.mvTableRow]
for comp_type in comps:
    with dpg.theme_component(comp_type, enabled_state=False):
        dpg.add_theme_color(dpg.mvThemeCol_Text, (0.50 * 255, 0.50 * 255, 0.50 * 255, 1.00 * 255))
        dpg.add_theme_color(dpg.mvThemeCol_Button, (45, 45, 48))
        dpg.add_theme_color(dpg.mvThemeCol_ButtonHovered, (45, 45, 48))
        dpg.add_theme_color(dpg.mvThemeCol_ButtonActive, (45, 45, 48))
lifeforce-dev commented 7 months ago

Just found this when having the same issue. Fwiw, this is in the documentation: https://dearpygui.readthedocs.io/en/latest/documentation/themes.html?highlight=enabled#theme-for-disabled-items

And modifying their example, this is what worked for me:

def main():
    dpg.create_context()
    gui = PackageSelectorGUI()

    dpg.create_viewport(title='Package Selector', width=600, height=300)
    dpg.setup_dearpygui()

    if gui.window_id is not None:
        dpg.set_primary_window(gui.window_id, True)

    disabled_color = (0.50 * 255, 0.50 * 255, 0.50 * 255, 1.00 * 255)
    disabled_button_color = (45, 45, 48)
    disabled_button_hover_color = (45, 45, 48)
    disabled_button_active_color = (45, 45, 48)
    with dpg.theme() as disabled_theme:
        with dpg.theme_component(dpg.mvButton, enabled_state=False):
            dpg.add_theme_color(dpg.mvThemeCol_Text, disabled_color, category=dpg.mvThemeCat_Core)
            dpg.add_theme_color(dpg.mvThemeCol_Button, disabled_button_color, category=dpg.mvThemeCat_Core)
            dpg.add_theme_color(dpg.mvThemeCol_ButtonHovered, disabled_button_hover_color, category=dpg.mvThemeCat_Core)
            dpg.add_theme_color(dpg.mvThemeCol_ButtonActive, disabled_button_active_color, category=dpg.mvThemeCat_Core)

        dpg.bind_theme(disabled_theme)

    dpg.disable_item("btn")

    dpg.show_viewport()
    dpg.start_dearpygui()
    dpg.destroy_context()
v-ein commented 6 months ago

I've done a bit of research on how themes are implemented, and here's what I've got.

There are several distinct issues with the themes:

I might create separate tickets on problems (2) and (3) just to describe them better. However, it won't really help because all three problems can only be solved by completely redesigning the theme hierarchy. It's quite a lot of work, so little chance that it gets implemented any time soon (if it gets implemented at all).

Bottomline: bad news, this issue is rather hard to fix.