MessageBox in DearPyGui

636 Views Asked by At

I am using the DearPyGui library for creating a user interface in python.

In a function that runs my algorithm, the algorithm needs some input from the user (yes/no question). Is it possible to easily implement such a messagebox in DearPyGui without braking the flow of the function?

Something like this:

def runAlgorithm():
    a = 2 + 2
    user_choice = dpg.messageBox("Do you want to add or subtract the values", ["add", "subtract"]
    if user_choice == "add":
        a = a + a
    else:
        a = a - a
    print("The user has selected %s and the result is %d"%(user_choice, a)

As I understand DearPyGui until now, this is not possible and I have to write something like this, which is quite bulky and unreadable and especially in algorithms that might need some user input greatly disrupts their readability.

def choiceAdd(sender, app_data, user_data):
    a = user_data[0]
    print("The user has selected %s and the result is %d"%("add", a + a)
def choiceSub(sender, app_data, user_data):
    a = user_data[0]
    print("The user has selected %s and the result is %d"%("subtract", a - a)

def runAlgorithm():
    a = 2 + 2
    with dpg.window():
        dpg.add_button("add", callback = choiceAdd, user_data = [a])
        dpg.add_button("subtract", callback = choiceSub, user_data = [a]
    user_choice = dpg.messageBox("Do you want to add or subtract the values", ["add", "subtract"]
    if user_choice == "add":
        a = a + a
    else:
        a = a - a
    print("The user has selected %s and the result is %d"%(user_choice, a)

Any help is recommended. Thank you in advance

1

There are 1 best solutions below

0
On

codes below maybe help

pythonic popup messagebox in dearpygui (asyncio or sync way)

target: pythonic popup messagebox in dearpygui

do_sth_step1(...)
user_response = msgbox('Confirm?')  # Yes/No
if user_response == 'Yes':
    do_sth_step2(...)

solution:

import time
import inspect
import dearpygui.dearpygui as dpg
dpg.create_context()

dpg_callback_queue = []


def msgbox():

    def on_msgbox_btn_click(sender, data, user_data):
        nonlocal resp
        resp = dpg.get_item_label(sender)
        dpg.hide_item(popup)
        # dpg.delete_item(popup)

    with dpg.popup(parent=dpg.last_item(), modal=True) as popup:
        dpg.add_text('goto step 2?')
        with dpg.group(horizontal=True):
            dpg.add_button(label='Yes', callback=on_msgbox_btn_click)
            dpg.add_button(label='No', callback=on_msgbox_btn_click)
    dpg.show_item(popup)

    resp = None
    while not resp:
        # print('waiting for response ...')
        time.sleep(0.01)  # sleep main thread also
        handle_callbacks_and_render_one_frame()  # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    return resp


def on_btn_click(sender, data, user_data):
    print('do sth step 1 ...')
    resp = msgbox()
    if resp == 'Yes':
        print('do sth step 2 ...')
    print('done!')


def main():
    with dpg.window(tag='prim'):
        dpg.add_button(label='Submit', callback=on_btn_click)
    dpg.create_viewport(title='test msgbox', width=600, height=300)

    # start_dpg()
    dpg.setup_dearpygui()
    dpg.set_primary_window('prim', True)
    dpg.show_viewport()
    dpg.configure_app(manual_callback_management=True)
    while dpg.is_dearpygui_running():
        handle_callbacks_and_render_one_frame()
    dpg.destroy_context()


def run_callbacks():
    global dpg_callback_queue
    while dpg_callback_queue:
        job = dpg_callback_queue.pop(0)
        if job[0] is None:
            continue
        sig = inspect.signature(job[0])
        args = []
        for i in range(len(sig.parameters)):
            args.append(job[i+1])
        result = job[0](*args)


def handle_callbacks_and_render_one_frame():
    global dpg_callback_queue
    dpg_callback_queue += dpg.get_callback_queue() or []  # retrieves and clears queue
    # print(f'jobs: {jobs}')
    run_callbacks()
    dpg.render_dearpygui_frame()


if __name__ == '__main__':
    main()

and asyncio way:

import asyncio
import inspect
import dearpygui.dearpygui as dpg
dpg.create_context()


async def msgbox():

    def on_msgbox_btn_click(sender, data, user_data):
        # print('clicked msgbox button')
        nonlocal resp
        resp = dpg.get_item_label(sender)
        dpg.hide_item(popup)
        # dpg.delete_item(popup)

    with dpg.popup(parent=dpg.last_item(), modal=True) as popup:
        dpg.add_text('goto step 2?')
        with dpg.group(horizontal=True):
            dpg.add_button(label='Yes', callback=on_msgbox_btn_click)
            dpg.add_button(label='No', callback=on_msgbox_btn_click)
    dpg.show_item(popup)

    resp = None
    while not resp:
        # print('waiting for response ...')
        await asyncio.sleep(0.01)

    return resp


async def on_btn_click(sender, data, user_data):
    print('do sth step 1 ...')
    resp = await msgbox()
    if resp == 'Yes':
        print('do sth step 2 ...')
    print('done')


async def main():
    with dpg.window(tag='prim'):
        dpg.add_button(label='Submit', callback=on_btn_click)
    dpg.create_viewport(title='test msgbox', width=600, height=300)

    # start_dpg()
    dpg.setup_dearpygui()
    dpg.set_primary_window('prim', True)
    dpg.show_viewport()
    dpg.configure_app(manual_callback_management=True)
    while dpg.is_dearpygui_running():
        jobs = dpg.get_callback_queue()  # retrieves and clears queue
        await run_callbacks(jobs)
        dpg.render_dearpygui_frame()
        await asyncio.sleep(0.01)
    dpg.destroy_context()


async def run_callbacks(jobs):
    if jobs is None:
        pass
    else:
        for job in jobs:
            if job[0] is None:
                continue
            sig = inspect.signature(job[0])
            args = []
            for i in range(len(sig.parameters)):
                args.append(job[i+1])
            result = job[0](*args)
            if inspect.isawaitable(result):
                asyncio.create_task(result)


if __name__ == '__main__':
    asyncio.run(main())