Dear PyGui (DPG)

repository·master·Indexed 12 days ago

https://github.com/hoffstadt/dearpygui

A modern, GPU-accelerated GUI framework for Python designed for high-performance applications such as real-time graphing and node editors. It provides a retained mode API utilizing DirectX11, Metal, or OpenGL/Vulkan for rendering. Features include a multithreaded architecture, a library of over 70 built-in widgets, and support for complex container hierarchies via context managers.

Tokens
54.7K
Snippets
127
Records
169
Agent score
97%

What's inside Dear PyGui

  1. What is Dear PyGui (DPG)

    master

    Dear PyGui (DPG) is a bloat-free, powerful Python GUI framework designed for creating quick and powerful interfaces for scripts.

    Unlike standard immediate-mode libraries like Dear ImGui, DPG provides a retained mode API for the developer, while utilizing an immediate-mode paradigm under the hood to allow for extremely dynamic interfaces.

    Key technical characteristics:

    • GPU Rendering: DPG does not use native OS widgets. Instead, it draws widgets directly using your graphics card via DirectX11, Metal, or Vulkan rendering APIs.
    • Performance: It is designed to be multithreaded and highly performant.
  2. Key features of Dear PyGui

    master

    DPG is distinguished from other Python GUI libraries by the following features:

    • GPU-accelerated rendering for smooth interfaces.
    • Multithreaded architecture.
    • High customizability of UI elements.
    • Built-in developer tools: Includes theme inspection, resource inspection, and runtime metrics.
    • Extensive Widget Library: Over 70 built-in widgets with hundreds of possible combinations.
  3. View Dear PyGui showcase applications

    master

    Dear PyGui can be used for various application types, including classic games and high-performance dynamic data visualizations. Examples of what can be built include:

    • Games: Tile-matching games like Tetris and arcade games like Snake. While Dear PyGui is not a dedicated game engine, it is capable of handling graphical animations.
    • High-Performance Visualizations: Dynamic graphs such as an Intensity graded FFT or a Digital Phosphor Display (e.g., using RTLSDR data).

    For inspiration, you can explore the source code of these community-developed applications.

  4. Organize items using Containers

    master

    Items can be organized into hierarchies using containers like window, group, and child_window.

    There are two ways to define parent-child relationships:

    1. Context Manager: Use with dpg.container_name(): to add items inside that container.
    2. Parent Parameter: Specify the parent argument in the add_** command to attach an item to an existing container tag.

    Containers can be nested to create complex layouts.

    import dearpygui.dearpygui as dpg
    
    dpg.create_context()
    
    with dpg.window(label="Tutorial"):
        dpg.add_button(label="Button 1")
        dpg.add_button(label="Button 2")
        with dpg.group():
            dpg.add_button(label="Button 3")
            dpg.add_button(label="Button 4")
            with dpg.group() as group1:
                pass
    
    # Adding items to an existing group via the parent parameter
    dpg.add_button(label="Button 6", parent=group1)
    dpg.add_button(label="Button 5", parent=group1)
    
    dpg.create_viewport(title='Custom Title', width=600, height=400)
    dpg.setup_dearpygui()
    dpg.show_viewport()
    dpg.start_dearpygui()
    dpg.destroy_context()
  5. Understand Dear PyGui terminology

    master

    To work effectively with Dear PyGui, familiarize yourself with these core concepts:

    • alias: A string used as a unique identifier in place of a standard integer ID. Aliases can be used anywhere a UUID is accepted.
    • item: Any object created within the library using a context manager (the with statement) or an add_ command (e.g., add_button).
    • root: An item that does not have a parent, such as a window or a registry.
    • window: A specific type of item created via add_window(...) that acts as a container for other items.
    • viewport: The actual window managed by the operating system that hosts the Dear PyGui application.
  6. How textures and images work in Dear PyGui

    master

    Dear PyGui (DPG) uses the GPU to render the GUI. To display an image, you cannot simply pass raw data to a widget; you must first create a texture containing the image data and upload it to the GPU via a texture_registry. Once created, the texture is identified by a tag (or alias), which is then passed to App Items to be rendered.

    Supported App Items for Textures:

    • mvDrawImage
    • mvImage
    • mvImageButton
    • mvImageSeries

    Textures are always handled as 1D lists or arrays. You can view all registered textures by using the show=True keyword in the texture_registry context manager.

    import dearpygui.dearpygui as dpg
    
    dpg.create_context()
    
    # 1. Create texture data
    texture_data = [1.0, 0.0, 1.0, 1.0] # Example RGBA
    
    # 2. Register the texture
    with dpg.texture_registry(show=True):
        dpg.add_static_texture(width=1, height=1, default_value=texture_data, tag="my_texture")
    
    # 3. Use the texture tag in a widget
    with dpg.window():
        dpg.add_image("my_texture")
    
    dpg.create_viewport()
    dpg.setup_dearpygui()
    dpg.show_viewport()
    dpg.start_dearpygui()
    dpg.destroy_context()
  7. Understand Item Callbacks (sender, app_data, user_data)

    master

    Most items in Dear PyGui (DPG) use callbacks to provide functionality when interacted with. Callbacks are submitted to a queue when an interaction occurs. A callback function can accept up to three positional arguments:

    1. sender: The tag of the item that triggered the callback (or 0 if triggered by the application).
    2. app_data: Data sent by DPG regarding the interaction (e.g., the current value of a widget).
    3. user_data: An optional argument used to pass custom Python objects into the function.

    Note: Because these are optional positional arguments, if you want to use the user_data keyword argument, you must still provide sender and app_data in the function signature.

    import dearpygui.dearpygui as dpg
    
    def button_callback(sender, app_data, user_data):
        print(f"Sender: {sender}")
        print(f"App Data: {app_data}")
        print(f"User Data: {user_data}")
    
    with dpg.window(label="Tutorial"):
        # Setting callback and user_data at creation
        dpg.add_button(label="Click Me", callback=button_callback, user_data="My Custom Data")
  8. How nodes and attributes work in imnodes

    master

    Imnodes uses an immediate-mode approach where the user is responsible for managing all state (IDs and connections).

    Core Concepts

    • Node Editor: A workspace instantiated within an ImGui window using BeginNodeEditor() and EndNodeEditor().
    • Nodes: Identified by unique integer IDs. You wrap node content between BeginNode(id) and EndNode().
    • Attributes (Pins): These are the connection points on nodes. They are either Input (left side) or Output (right side). Attributes must also have unique integer IDs. You can nest standard ImGui widgets inside attributes.
    • Links: Connections between two attribute pins. A link is defined by a unique integer ID and a pair of attribute IDs (start and end).
    // 1. Create the editor workspace
    ImGui::Begin("node editor");
    ImNodes::BeginNodeEditor();
    
    // 2. Create a node
    const int node_id = 1;
    ImNodes::BeginNode(node_id);
    
      // 3. Add a Title Bar (optional, must be called first)
      ImNodes::BeginNodeTitleBar();
      ImGui::TextUnformatted("My Node");
      ImNodes::EndNodeTitleBar();
    
      // 4. Add an Output Attribute (Pin)
      const int output_attr_id = 2;
      ImNodes::BeginOutputAttribute(output_attr_id);
      ImGui::Text("output pin");
      ImNodes::EndOutputAttribute();
    
    ImNodes::EndNode();
    
    // 5. Render existing links
    // links is a vector of std::pair<int, int> (start_attr, end_attr)
    for (int i = 0; i < links.size(); ++i) {
      ImNodes::Link(i, links[i].first, links[i].second);
    }
    
    ImNodes::EndNodeEditor();
    ImGui::End();
  9. How tooltips work in Dear PyGui

    master

    A tooltip is a container-based UI element that is conditionally rendered based on the hover state of a parent item.

    Key Mechanics:

    1. Triggering: The tooltip is linked to a parent item using the parent's tag passed as the first argument to the tooltip creation function.
    2. Composition: Since tooltips are containers, they follow the standard Dear PyGui hierarchy pattern where you can nest other widgets inside them to create complex informational popups.
  10. Use the Value Storage System

    master

    Instead of storing values strictly inside the widget object, Dear PyGui uses a central key-value storage system. This allows multiple widgets to manipulate the same underlying value.

    • Source Keyword: Every widget has a source keyword. By default, source is equal to the widget's name/ID. If you set multiple widgets to use the same source, they will all track and manipulate the same value.
    • Requirements: If multiple widgets share a source, they must have the same data type and size.
    • Pre-defining Values: If you are linking widgets of different types or sizes to a single key, use add_value to pre-define the value in the storage system.
  11. How the Node Editor components work together

    master

    The Node Editor is a schematic/graph interface composed of four main hierarchical components:

    1. Node Editor: The top-level container area where nodes reside.
    2. Nodes: Floating containers that hold attributes.
    3. Attributes: Collections of UI widgets that feature 'pins'. Attributes can be configured as Input, Output, or Static.
    4. Links: The visual connections established between attributes.

    Important Lifecycle Note: When a user drags an attribute pin to create a connection, the Node Editor triggers a callback. DearPyGui does not automatically create the link; the developer must use the provided app_data within the callback to call dpg.add_node_link().

    import dearpygui.dearpygui as dpg
    
    dpg.create_context()
    
    # The developer is responsible for creating the link in this callback
    def link_callback(sender, app_data):
        # app_data contains (link_id1, link_id2) or (attr_id1, attr_id2)
        dpg.add_node_link(app_data[0], app_data[1], parent=sender)
    
    with dpg.node_editor(callback=link_callback):
        with dpg.node(label="Node"):
            with dpg.node_attribute(label="Attr"):
                dpg.add_button(label="Inside Attribute")