# Dear ImGui Bundle: the book, in plain text The pages of the book for users (https://imgui-bundle.pages.dev/doc/), one after the other: what the bundle is, how to install it, the core libraries, the add-ons, the notes for Python and for C++. Each page starts with its URL. The pictures are left out, and so are the developer docs (how to build the bundle and its bindings). The guide for AI assistants: https://imgui-bundle.pages.dev/llms.txt The API, in plain text: https://imgui-bundle.pages.dev/llms/api/index.txt The demos, with their code: https://imgui-bundle.pages.dev/llms/demos.txt -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/what-is-imgui-bundle/ # What is Dear ImGui Bundle? Dear ImGui Bundle is a "batteries included" framework built on [Dear ImGui](https://github.com/ocornut/imgui). It bundles 20+ libraries for plotting, markdown, node editors, 3D gizmos, and more - all working seamlessly in **C++ and Python**, on **all major platforms** (Windows, Linux, macOS, iOS, Android, WebAssembly). If you are building scientific tools, game tools, visualization applications, developer tools, or creative apps, give it a try. You'll soon see that GUI code can be clear, readable, and easy to maintain. The immediate mode paradigm makes it a joy to reason about your app logic. **Key highlights:** - **Immediate mode**: Your code reads like a book. No widget trees, no callbacks, no synchronization headaches. - **Cross-platform**: Same code runs on desktop, mobile, and web (via Emscripten or Pyodide). - **Python-first**: Full Python bindings with type hints and IDE autocompletion. - **Always up-to-date**: Tracks Dear ImGui upstream closely; Python bindings are auto-generated. --- ## Code That Reads Like a Book The immediate mode paradigm means your UI code is simple and direct: the app below can be coded with just 9 readable lines of Python: ```python from imgui_bundle import imgui, hello_imgui selected_idx = 0 items = ["Apple", "Banana", "Cherry"] def gui(): global selected_idx imgui.text("Choose a fruit:") _, selected_idx = imgui.list_box("##fruits", selected_idx, items) imgui.text(f"You selected: {items[selected_idx]}") hello_imgui.run(gui, window_title="Fruit Picker") ``` The relation between code and behavior is direct: what you write is what runs. There are no hidden widget trees, no callback chains, and no implicit state synchronization. This makes it easier to reason about your app's logic and flow. **Easy to understand for humans** Being able to work with readable code is getting more and more important as LLMs are now widely used to generate code: *You*, the human, still need to understand, review, and maintain that code. Immediate mode makes this easier. **Easy to understand for AI** And the same clarity that helps humans also helps AI: with no implicit state to get wrong, LLMs can read and generate ImGui code reliably. The [full PDF manuals](https://imgui-bundle.pages.dev/doc/assets/imgui_bundle_book.pdf) give an AI assistant all the context it needs. Tip: **Try it in your browser — no install needed:** [Open the Online Python Playground](https://imgui-bundle.pages.dev/playground/) --- ## Who is it for? - **beginners and developers**: go from idea to GUI prototype in minutes, without learning a complex framework. Deploy to almost any platform. - **ML/AI researchers**: visualize training in real time, tune hyperparameters mid-run, inside Jupyter - **Computer vision engineers**: inspect images and tensors at the pixel level with ImmVision - **Robotics developers**: fast, readable debug UIs in Python or C++ - **Scientific instrument builders**: cross-platform GUIs that deploy to desktop and web from the same code - **Technical tool makers**: build node editors, gizmos, code editors without a web stack - **Teachers and science communicators**: interactive lessons that open from a link, on a computer or a phone, such as [Grokking](https://imgui-bundle.pages.dev/playground/?demo=explorables/grokking/grokking.py) or the [logistic map](https://imgui-bundle.pages.dev/playground/?demo=explorables/logistic_map.py) **Who is this project not for** You should prefer a more complete framework (such as Qt for example) if your intent is to build a fully fledged application, with support for accessibility, internationalization, or the platform's native look. The style itself is not the limit: 17 themes, tweaked live, though not with CSS. Its strength lies elsewhere: the same code runs on the desktop, in the browser and on phones, in C++ as in Python, and it is fast. Qt comes closest, but its Python does not run in the browser. --- ## Learn More - **[Key Features](https://imgui-bundle.pages.dev/doc/intro/key-features/)** — Library list, FAQ, and more details. - **[Immediate Mode Explained](https://imgui-bundle.pages.dev/doc/intro/imm-gui/)** — Understand the paradigm that makes ImGui different. - **[Interactive Manuals & Demos](https://imgui-bundle.pages.dev/doc/intro/interactive-manuals/)** — Try the demos in your browser. - **[Hello ImGui and ImmApp](https://imgui-bundle.pages.dev/doc/core-libs/hello-imgui-immapp/)** — High-level runners that take care of the app loop, windowing, and assets management, so that you can start an app with a single line of code. - **[Jupyter Notebooks](https://imgui-bundle.pages.dev/doc/python/notebook-runners/)** — Interactive GUIs inside Jupyter. Your training loop keeps running while you tune hyperparameters. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/key-features/ # Key Features ## Works everywhere * **Cross-platform in C++ and Python:** Works on Windows, Linux, macOS, iOS, Android, and WebAssembly! * **Web ready**: Develop full web applications, in C++ via Emscripten; or in Python thanks to ImGui Bundle's integration within Pyodide. ## First class support for Python * **Python Bindings:** Using Dear ImGui Bundle in Python is extremely easy and productive. * **Well documented Python bindings and stubs:** The Python bindings stubs reflect the C++ API and documentation, serving as a reference and aiding autocompletion in your IDE. See for example the [stubs for imgui](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui/__init__.pyi), and [for hello_imgui](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/hello_imgui.pyi). * Use it to create **standalone apps** (on Windows, macOS, and Linux), or to add **interactive UIs to your notebooks**. Deploy your apps **on the web** with ease, using [Pyodide](https://pyodide.org/en/stable/). ## Easy to use & well documented * The Immediate Mode GUI (IMGUI) paradigm is simple and powerful, letting you focus on the creative aspects of your projects. * **Easy to use, yet very powerful:** Start your first app in 3 lines. * **Interactive Demos and Documentation:** Quickly get started with the ImGui Bundle Interactive Explorer, that showcases the capabilities of the pack. Read or copy-paste the source code (Python and C++) directly from there! ## Always up-to-date * **Auto-generated bindings:** Python bindings are automatically generated, ensuring they stay synchronized with C++ APIs. * **Version tracking:** ImGui Bundle version numbers match Dear ImGui releases (e.g., ImGui Bundle 1.91.x includes Dear ImGui 1.91.x). Updates typically follow within days of upstream releases. ## High performance * **Fast:** Rendering is done via OpenGL (or any other renderer you choose), through native code. # Comprehensive Library Integration Dear ImGui Bundle isn't just ImGui - it's a curated ecosystem with more than 20 integrated libraries, where Each library is: - Available in Python and C++ with consistent APIs - Always up to date, since Python bindings are autogenerated - Documented with interactive examples ### Core Libraries * Dear ImGui : Bloat-free Graphical User interface with minimal dependencies * ImGui Test Engine : Dear ImGui Tests & Automation Engine * Hello ImGui : cross-platform Gui apps with the simplicity of a "Hello World" app ### Plotting & Visualization * ImPlot : Immediate Mode Plotting * ImPlot3D : Immediate Mode 3D Plotting * ImmVision : Immediate image debugger and insights * imgui_tex_inspect : A texture inspector tool for Dear ImGui ### Text Editing & Markdown * ImGuiColorTextEdit : Colorizing text editor for ImGui * imgui_rich_md : Markdown renderer for Dear ImGui using the MD4C parser, with LaTeX math and syntax-highlighted code blocks (based on imgui_md) ### Tools * ImGuizmo : Immediate mode 3D gizmo for scene editing * imgui-node-editor : Node Editor built using Dear ImGui * NanoVG : Antialiased 2D vector drawing library on top of OpenGL ### Widgets * ImFileDialog : A file dialog library for Dear ImGui * portable-file-dialogs : _OS native_ file dialogs library (C++11, single-header) * imgui-knobs : Knobs widgets for ImGui * imspinner : Set of nice spinners for imgui * imgui_toggle : A toggle switch widget for Dear ImGui * ImCoolBar : A Cool bar for Dear ImGui * imgui-command-palette : A Sublime Text or VSCode style command palette in ImGui # Common Questions ## Is it up to date? **Yes!** Because: Python bindings are auto-generated, so they stay in sync with C++ ## "Isn't rebuilding the UI every frame slow?" **No!** Because: - Widget calls are cheap (just generate drawing commands) - Actual rendering is GPU-accelerated - Typical frame times: < 1ms for most UIs - Easily achieves 60+ FPS even with complex interfaces ## "How's the Python performance?" **Excellent!** Because: - Each widget call crosses to C++ once per frame - Heavy lifting (rendering) is in C++ - Python overhead is < 0.5ms per frame typically - Real bottleneck is usually your application logic, not the GUI ## "Does it work on the web?" **Yes, impressively!** - C++ → Emscripten → WebAssembly - Python → Pyodide → WebAssembly (!!) - Full Python runtime in browser - Native-speed rendering via WebGL - Check [ImGui Bundle Explorer](https://imgui-bundle.pages.dev/explorer/) ## Is It Interesting for Developers? **Absolutely yes**, for several reasons: * The immediate-mode paradigm is genuinely refreshing: your code directly expresses intent * Rapid Development: From zero to functional UI is remarkably fast: * The cross-platform support actually works: the same code runs on Windows, macOS, Linux. Mobile support is real (in C++), and web support via Emscripten and Pyodide also. * Active Community: Dear ImGui itself has 70k+ stars. Dear ImGui Bundle adds comprehensive Python support, and has 1k+ stars (growing steadily). -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/imm-gui/ # Immediate GUI # What is an Immediate GUI An "Immediate Mode Graphical User Interface" lets you build user interfaces directly in code. This keeps the UI and app state in perfect sync with minimal boilerplate. This approach is especially popular for quick prototyping and tools because it's intuitive, flexible, easy to maintain, and trivial to debug. The example below shows a documented example to explain the Immediate Mode GUI paradigm: Python: ```python from imgui_bundle import imgui, immapp counter = 0 # our app state # The gui() function is called every frame, so the UI updates in real time. def gui(): global counter # The state of the UI is always in sync with the app state, # via standard variables: debugging UI becomes trivial! imgui.text(f"Counter ={counter}") # We can display a button, and handle its action in one line: if imgui.button("increment counter"): counter += 1 # Below, we can also set the counter value via a slider between 0 and 100 value_changed, counter = imgui.slider_int("Set counter", counter, 0, 100) # Run the app (in one line!) immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui.h" int counter = 0; // our app state // The gui() function is called every frame, so the UI updates in real time. void gui() { // The state of the UI is always in sync with the app state, // via standard variables: debugging UI becomes trivial! ImGui::Text("Counter =%d", counter); // We can display a button, and handle its action in one line: if (ImGui::Button("increment counter")) counter += 1; // Below, we can also set the counter value via a slider between 0 and 100 ImGui::SliderInt("Set counter", &counter, 0, 100); } // Run the app (in one line!) int main(int, char **) { ImmApp::Run(gui); } ``` It produces this simple app: **Immediate Mode GUI does not mean that you cannot separate concerns!** You can still (and should) maintain a separate application state. The key difference is that your GUI can interact directly with that state in a straightforward way, without the need to maintain a separate UI state or complex event handling systems. # Dear ImGui The most popular Immediate Mode GUI library is [Dear ImGui](https://github.com/ocornut/imgui), a powerful **C++** library originally created for real-time tools in game engines, now widely used in many industries, with over 60k stars on GitHub. Dear ImGui Bundle includes Dear ImGui plus many extra libraries, making it ideal for rapid prototyping as well as building complex apps with advanced widgets, plotting, node editors; in C++ and Python. # Get started in no time with Hello ImGui and ImmApp With Hello ImGui and ImmApp (both included in Dear ImGui Bundle), you can create a full-featured GUI application with just a few lines of code. * [Hello ImGui](https://pthom.github.io/hello_imgui) is a library based on ImGui that enables to easily create applications with ImGui. It handles window creation, backend initialization (SDL, GLFW, etc.), cross-platform assets, docking layout, and more. * [ImmApp](https://github.com/pthom/imgui_bundle/blob/main/external/immapp/immapp/runner.h) (aka "Immediate App", a submodule of ImGuiBundle) is a thin extension of Hello ImGui that enables to easily initialize the ImGuiBundle addons that require additional setup at startup. ## Hello World in 4 lines 4 lines are enough to start a GUI application! Python: ```python from imgui_bundle import imgui, immapp def gui(): imgui.text("Hello, world!") immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui.h" void gui() { ImGui::Text("Hello, world!"); } int main() { ImmApp::Run(gui); } ``` ## A more complete example with plots The example below shows how to create a more complete application that uses an add-on (ImPlot) for plotting data. Python: ```python import time import numpy as np from imgui_bundle import implot, imgui, immapp, imgui_knobs, hello_imgui # Fill x and y whose plot is a heart vals = np.arange(0, np.pi * 2, 0.01) x = np.power(np.sin(vals), 3) * 16 y = 13 * np.cos(vals) - 5 * np.cos(2 * vals) - 2 * np.cos(3 * vals) - np.cos(4 * vals) # Heart pulse rate and time tracking phase = 0.0 t0 = time.time() + 0.2 heart_pulse_rate = 80 def gui(): global heart_pulse_rate, phase, t0, x, y # Change heart size over time, according to the pulse rate t = time.time() phase += (t - t0) * heart_pulse_rate / (np.pi * 2) k = 0.8 + 0.1 * np.cos(phase) t0 = t # Plot the heart if implot.begin_plot("Heart", immapp.em_to_vec2(21, 21)): implot.plot_line("", x * k, y * k) implot.end_plot() # The heart beats on its own: the app keeps its full speed while the plot is visible hello_imgui.set_item_is_live() # let the user set the pulse rate via a knob _, heart_pulse_rate = imgui_knobs.knob("Pulse Rate", heart_pulse_rate, 30.0, 180.0) if __name__ == "__main__": immapp.run(gui, window_size_auto=True, window_title="Hello!", with_implot=True) ``` C++: ```cpp #include "imgui.h" #include "implot/implot.h" #include "imgui-knobs/imgui-knobs.h" #include "immapp/immapp.h" #include "hello_imgui/hello_imgui.h" #include std::vector VectorTimesK(const std::vector& values, double k) { std::vector r(values.size(), 0.); for (size_t i = 0; i < values.size(); ++i) r[i] = k * values[i]; return r; } int main(int , char *[]) { // Fill x and y whose plot is a heart double pi = 3.1415926535; std::vector x, y; { for (double t = 0.; t < pi * 2.; t += 0.01) { x.push_back(pow(sin(t), 3.) * 16.); y.push_back(13. * cos(t) - 5 * cos(2. * t) - 2 * cos(3. * t) - cos(4. * t)); } } // Heart pulse rate and time tracking double phase = 0., t0 = ImmApp::ClockSeconds() + 0.2; float heart_pulse_rate = 80.; auto gui = [&]() { // Change heart size over time, according to the pulse rate double t = ImmApp::ClockSeconds(); phase += (t - t0) * (double)heart_pulse_rate / (pi * 2.); double k = 0.8 + 0.1 * cos(phase); t0 = t; auto xk = VectorTimesK(x, k), yk = VectorTimesK(y, k); // Plot the heart if (ImPlot::BeginPlot("Heart", ImmApp::EmToVec2(21, 21))) { ImPlot::PlotLine("", xk.data(), yk.data(), (int)xk.size()); ImPlot::EndPlot(); // The heart beats on its own: the app keeps its full speed while the plot is visible HelloImGui::SetItemIsLive(); } // let the user set the pulse rate via a knob ImGuiKnobs::Knob("Pulse", &heart_pulse_rate, 30., 180.); }; ImmApp::AddOnsParams addOnsParams{.withImplot = true}; HelloImGui::SimpleRunnerParams runnerParams { .guiFunction = gui, .windowTitle = "Hello!", .windowSizeAuto = true, }; ImmApp::Run(runnerParams, addOnsParams); } ``` # Quickly deploy your apps on the web These apps can be easily deployed on the web, either in C++ via Emscripten, or in Python via Pyodide. * Online demo (C++/Emscripten): [Heart Pulse Demo](https://imgui-bundle.pages.dev/explorer/haiku_implot_heart.html) * Online demo (Python/Pyodide): [Heart Pulse Demo - Pyodide](https://imgui-bundle.pages.dev/min_pyodide_app/demo_heart), and [html + python source code](https://imgui-bundle.pages.dev/min_pyodide_app/demo_heart.source.txt) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/compare/ # How Does It Compare? Not sure if Dear ImGui Bundle is right for you? Compare the code styles with other popular GUI libraries, when creating the app below: ImGui Bundle: **12 lines** – True immediate mode: UI declaration *is* the event handler ```python from imgui_bundle import imgui, hello_imgui selected_idx = 0 items = ["Apple", "Banana", "Cherry"] def gui(): global selected_idx imgui.text("Choose a fruit:") _changed, selected_idx = imgui.list_box("##fruits", selected_idx, items) imgui.text(f"You selected: {items[selected_idx]}") hello_imgui.run(gui, window_title="Fruit Picker", window_size_auto=True) ``` **Strengths**: Simplest code, real-time capable, runs on desktop + web (Pyodide), 20+ integrated libraries, full C++ support **Best for**: Tools, visualization, games, scientific apps Qt: **31 lines** – Retained mode with class hierarchy and signals/slots ```python from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QListWidget items = ["Apple", "Banana", "Cherry"] class FruitPicker(QWidget): def __init__(self): super().__init__() layout = QVBoxLayout() self.label = QLabel("Choose a fruit:") self.list_widget = QListWidget() self.list_widget.addItems(items) self.result_label = QLabel(f"You selected: {items[0]}") self.list_widget.currentRowChanged.connect(self.on_selection_changed) layout.addWidget(self.label) layout.addWidget(self.list_widget) layout.addWidget(self.result_label) self.setLayout(layout) def on_selection_changed(self, index): self.result_label.setText(f"You selected: {items[index]}") app = QApplication([]) window = FruitPicker() window.show() app.exec() ``` **Qt strengths**: More widgets, Qt Designer, larger ecosystem, rich text, accessibility, native look **ImGui Bundle strengths**: Simpler code, real-time, lighter weight, scientific viz, easier cross-compilation **Qt is Best for**: Traditional business apps, enterprise software DearPyGui: **29 lines** – ImGui-based but with retained-mode API and callbacks ```python import dearpygui.dearpygui as dpg items = ["Apple", "Banana", "Cherry"] dpg.create_context() def on_selection_changed(sender, app_data): dpg.set_value("result_label", f"You selected: {app_data}") with dpg.window(tag="Primary Window", label="Fruit Picker"): dpg.add_text("Choose a fruit:") dpg.add_listbox(items=items, callback=on_selection_changed, num_items=len(items)) dpg.add_text("You selected: ", tag="result_label") dpg.create_viewport(title='Fruit Picker', width=400, height=300) dpg.setup_dearpygui() dpg.show_viewport() dpg.set_primary_window("Primary Window", True) dpg.start_dearpygui() dpg.destroy_context() ``` **DearPyGui strengths**: Familiar retained-mode API, large user base, good reputation **ImGui Bundle strengths**: True immediate mode, more libraries (~20), C++ support, Pyodide web support **DearPyGui is Best for**: Developers who prefer retained-mode patterns NiceGUI: **15 lines** – Web-based with callbacks ```python from nicegui import ui selected_idx = -1 items = ["Apple", "Banana", "Cherry"] def on_selection_change(e): global selected_idx selected_idx = items.index(e.value) selection_label.text = f"You selected: {e.value}" ui.label("Choose a fruit:") dropdown = ui.select(options=items, value=items[0], on_change=on_selection_change) selection_label = ui.label(f"You selected: {items[0]}") ui.run(title="Fruit Picker") ``` **NiceGUI strengths**: Web-native, modern UI, easy deployment, familiar web paradigm, reactive **ImGui Bundle strengths**: Native performance, desktop-native, offline capable, advanced widgets, lower latency **NiceGUI is Best for**: Web-first apps, internal dashboards, CRUD interfaces Gradio: **18 lines** – Declarative blocks with event wiring ```python import gradio as gr items = ["Apple", "Banana", "Cherry"] selected_item = items[0] def on_selection_change(choice): global selected_item selected_item = choice return f"You selected: {choice}" with gr.Blocks() as demo: gr.Markdown("# Fruit Picker") gr.Markdown("Choose a fruit:") dropdown = gr.Dropdown(choices=items, value=items[0], label="Choose a fruit") output = gr.Textbox(value=f"You selected: {items[0]}", label="Selection", interactive=False) dropdown.change(fn=on_selection_change, inputs=dropdown, outputs=output) demo.launch() ``` **Gradio strengths**: Web-native, ML-focused, Hugging Face integration, easy sharing, pre-built media components **ImGui Bundle strengths**: Native performance, desktop-native, stateful apps, professional tools, flexibility **Gradio is Best for**: ML model demos, Hugging Face Spaces, sharing with non-technical users Note: These examples are [available here](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/demos_python/sandbox/compare_other_libs) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/interactive-manuals/ # Interactive Manuals ## Dear ImGui Explorer [Dear ImGui Explorer](https://pthom.github.io/imgui_explorer/) lets you explore all the widgets and features of Dear ImGui, with live examples and the corresponding python or C++ code. It is built using Dear ImGui Bundle. Its "API" tab documents the code: click a name in the code, then the book button, and you get its Python and C++ signatures, its doc, where the demo uses it, and links to the [API reference](https://imgui-bundle.pages.dev/doc/api/). A tooltip gives the same for the identifier under the mouse. ## Dear ImGui Bundle Explorer [Dear ImGui Bundle Explorer](https://imgui-bundle.pages.dev/explorer/): interactive reference manual - browse demos, see the code, try the widgets. It opens on a welcome page, with a carousel of what the bundle can do. Its "Demos" page is the catalog of demos, by category: starter apps, tours of the libraries, interactive manuals, each with its Python and C++ code. ## Online Python Playground [Online Python Playground](https://imgui-bundle.pages.dev/playground/): an online Python sandbox with ready-to-run demos - edit code, see results instantly. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/examples-gallery/ # Made with Dear ImGui Bundle Applications built with Dear ImGui Bundle. More in the [Gallery](https://github.com/pthom/imgui_bundle/discussions/107): add yours! The bundle's own demos are in [Demos & Tutorials](https://imgui-bundle.pages.dev/doc/intro/demos/). ## 4K4D A research project aimed for CVPR 2024, using python bindings (ImGui Bundle). ``` @inproceedings{xu20244k4d, title={4K4D: Real-Time 4D View Synthesis at 4K Resolution}, author={Xu, Zhen and Peng, Sida and Lin, Haotong and He, Guangzhao and Sun, Jiaming and Shen, Yujun and Bao, Hujun and Zhou, Xiaowei}, booktitle={CVPR}, year={2024} } ``` [ 4K4D: Real-Time 4D View Synthesis at 4K Resolution](https://zju3dv.github.io/4k4d/) A volumetric video, showing an ImGui interface to control the rendering parameters. ## HDRview [HDRview](https://github.com/wkjarosz/hdrview) is a research-oriented image viewer with an emphasis on examining and comparing high-dynamic range (HDR) images. It is developed by Wojciech Jarosz and is built using Hello ImGui (which is included in Dear ImGui Bundle), in C++. It runs on Windows, Linux, macOS, iOS, and on the web via emscripten! An HDR photograph open in HDRview, alongside several multi-view and multi-part EXRs, with the Log window open below the viewport. Access HDRview online: [https://wkjarosz.github.io/hdrview/]( https://wkjarosz.github.io/hdrview/) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/intro/resources/ # Resources ## Start here - [Home page](https://imgui-bundle.pages.dev/): the project's site - [Interactive Explorer](https://imgui-bundle.pages.dev/explorer/): all the libraries, with live demos and their C++ and Python code - [Python Playground](https://imgui-bundle.pages.dev/playground/): a live Python sandbox with ready-to-run demos: edit the code, see the result at once - [Documentation](https://imgui-bundle.pages.dev/doc/): the full documentation, with the [API reference](https://imgui-bundle.pages.dev/doc/api/) of every library - [GitHub](https://github.com/pthom/imgui_bundle): the source code, issues and discussions - [Discord](https://discord.gg/xkzpKMeYN3): the community, for questions, showcase and discussion - [DeepWiki](https://deepwiki.com/pthom/imgui_bundle): AI-powered Q&A about the framework ## Documentation - [Dear ImGui Bundle documentation](https://imgui-bundle.pages.dev/doc/), also as a [PDF](https://imgui-bundle.pages.dev/doc/assets/imgui_bundle_book.pdf) - [API reference](https://imgui-bundle.pages.dev/doc/api/): every function, class and enum of each library, with its Python and C++ signatures; also [in plain text](https://imgui-bundle.pages.dev/llms/api/index.txt), for AI assistants - [For AI assistants](https://imgui-bundle.pages.dev/doc/intro/ai-guide/): a page written for them (also at https://imgui-bundle.pages.dev/llms.txt), and the book [in plain text](https://imgui-bundle.pages.dev/llms-full.txt) - [Hello ImGui documentation](https://pthom.github.io/hello_imgui), also as a [PDF](https://pthom.github.io/hello_imgui/hello_imgui_book.pdf). Hello ImGui provides a simple framework to quickly create applications using Dear ImGui. It is included in Dear ImGui Bundle. - [Fiatlight documentation](https://pthom.github.io/fiatlight), also as a [PDF](https://pthom.github.io/fiatlight/flgt.pdf). Fiatlight provides automatic UI generation for functions and structured data (dataclasses, pydantic models), making it a powerful tool for rapid prototyping and application development. It is built on top of Dear ImGui Bundle. - [litgen documentation](https://pthom.github.io/litgen/): the generator of the Python bindings You may also upload the PDF manuals to a chat with an AI assistant, so that it can help you when using the libraries. [Ask DeepWiki](https://deepwiki.com/pthom/imgui_bundle): DeepWiki makes it easy to search and ask questions about Dear ImGui Bundle and its integrated libraries. It is generated by AI, based on the full source code and documentation. Quite useful, even if some inconsistencies may occur. (for [Dear ImGui](https://deepwiki.com/ocornut/imgui) - [Dear ImGui Bundle](https://deepwiki.com/pthom/imgui_bundle) - [Hello ImGui](https://deepwiki.com/pthom/hello_imgui)) ## Interactive manuals The manuals and demos below are using Dear ImGui Bundle itself! - [Dear ImGui Bundle Explorer](https://imgui-bundle.pages.dev/explorer/): interactive reference manual - browse demos, see the code, try the widgets - [Online Python Playground](https://imgui-bundle.pages.dev/playground/): live Python sandbox with ready-to-run demos - edit code, see results instantly - [Dear ImGui Explorer](https://pthom.github.io/imgui_explorer/): interactive manual for Dear ImGui, ImPlot, ImPlot3D ## Community - [Discord](https://discord.gg/xkzpKMeYN3): join the community for questions, showcase, and discussion - [GitHub Discussions](https://github.com/pthom/imgui_bundle/discussions): searchable Q&A - [FAQ](https://github.com/pthom/imgui_bundle/issues?q=is%3Aissue+label%3AFAQ): answers to common questions, as issues ## Repositories - [Dear ImGui official repository](https://github.com/ocornut/imgui) - [Dear ImGui Bundle repository](https://github.com/pthom/imgui_bundle) - [Hello ImGui repository](https://github.com/pthom/hello_imgui) - [Litgen (bindings generator) repository](https://github.com/pthom/litgen) - [Fiatlight repository](https://github.com/pthom/fiatlight) ## Videos A series of video tutorials about Dear ImGui Bundle, Hello ImGui and Fiatlight: - [Dear ImGui Bundle - YouTube Playlist](https://www.youtube.com/playlist?list=PLaJx_KrDECZPzttQ77Gv8DD7OAUwmtWUc) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-imgui-intro/ # Introduction # Immediate GUI in Python with Dear ImGui Bundle The most popular Immediate Mode GUI library is [Dear ImGui](https://github.com/ocornut/imgui), a powerful **C++** library originally created for real-time tools in game engines, now widely used in many industries, with over 60k stars on GitHub. For Python, [Dear ImGui Bundle](https://github.com/pthom/imgui_bundle) brings full Dear ImGui support plus many extra libraries, making it ideal for rapid prototyping as well as building complex apps with advanced widgets, plotting, node editors, and more. The python bindings are heavily documented so that they are easy to browse. They are also autogenerated, so that they are always up-to-date. # Anatomy of an application with Dear ImGui Bundle `imgui_bundle` is a Python package that unifies multiple Dear ImGui-related submodules: * `imgui`: the core Dear ImGui library * `implot` and `implot3d`: for advanced, real-time plotting * `rich_md`: markdown rendering for imgui * `hello_imgui`: an approachable starter kit for new apps * `immapp`: helper to activate "addons" (like implot, markdown, etc.) * Plus about 20 other powerful tools The example below is heavily commented and shows how to create a simple app that combines Markdown text and an animated plot using `implot`: ```python import numpy as np from imgui_bundle import imgui, implot, rich_md, hello_imgui, immapp def gui(): # Render Markdown text rich_md.render(""" # Render an animated plot with ImPlot This example uses `ImPlot` for real-time plotting, and `rich_md` for markdown. """) # Render an animated plot (updates every frame) if implot.begin_plot( title_id="Plot", # size in em units (1em = height of a character) size=hello_imgui.em_to_vec2(40, 20)): x = np.arange(0, np.pi * 4, 0.01) y = np.cos(x + imgui.get_time()) implot.plot_line("y1", x, y) implot.end_plot() if imgui.button("Exit"): hello_imgui.get_runner_params().app_shall_exit = True # Run the app with ImPlot and markdown support immapp.run(gui, with_implot=True, with_markdown=True, window_size=(700, 500)) ``` # Deploy your applications Dear ImGui Bundle apps are highly portable—they can run as standalone Python scripts, in Jupyter notebooks, or even directly in web browsers via Pyodide. * **Standalone scripts:** Run on any PC (Windows, macOS, Linux) with minimal setup. * **Jupyter notebooks:** The app runs in a separate window, and a screenshot is displayed in the notebook after closing (requires running Jupyter locally). * **Web (Pyodide):** No server or installation required—just a static HTML file. Your Python app runs in the browser, with the package downloaded from a CDN. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-install/ # Install for Python ## Install from pypi ```bash # Minimal install pip install imgui-bundle # or to get all optional features: pip install "imgui-bundle[full]" ``` Binary wheels are available for Windows, macOS and Linux. If a compilation from source is needed, the build process might take up to 5 minutes, and will require an internet connection. *Platform notes* * _Windows_: Under windows, you might need to install the [msvc redist](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2015-2017-2019-and-2022) * _macOS_ : under macOS, if a binary wheel is not available (e.g. for older macOS versions), pip will try to compile from source. This might fail if you do not have XCode installed. In this case, install imgui-bundle with the following command `SYSTEM_VERSION_COMPAT=0 pip install --only-binary=:all: imgui_bundle` ## Install from source ```bash # Clone the repository git clone https://github.com/pthom/imgui_bundle.git cd imgui_bundle # Build and install the package (minimal install) pip install -v . # or build and install the package with all optional features: # pip install -v ".[full]" ``` The build process might take up to 5 minutes, and will clone the submodules if needed (an internet connection is required). ## Run the python demo The demo needs the optional features: after a minimal install, it stops at start ("Dear ImGui Bundle Explorer requires numpy!"). ```bash pip install "imgui-bundle[full]" imgui_bundle_demo ``` The source for the demos can be found inside [bindings/imgui_bundle/demos_python](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/demos_python). TIP: Consider `imgui_bundle_demo` as an always available manual for Dear ImGui Bundle with lots of examples and related code source. ## Next Steps - **[Dear ImGui Basics](https://imgui-bundle.pages.dev/doc/core-libs/imgui/)** – Learn ImGui concepts (widgets, IDs, patterns) - **[Hello ImGui & ImmApp](https://imgui-bundle.pages.dev/doc/core-libs/hello-imgui-immapp/)** – App runners, configuration, DPI handling - **[Python Tips](https://imgui-bundle.pages.dev/doc/python/python-tips/)** – Context managers, C++ to Python translation, debugging - **[Assets](https://imgui-bundle.pages.dev/doc/python/python-assets/)** – Managing fonts, images, and resources -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-assets/ # Assets folder (for python) hello_imgui and immapp applications rely on the presence of an `assets/` folder. **This folder stores:** * Default fonts used by the markdown renderer (if the markdown addon is used). * All the resources (images, fonts, etc.) used by the application. Feel free to add any resources there! **Assets folder location** Place the assets folder in the same folder as the script. **If needed, change the assets folder location:** Call `hello_imgui.set_assets_folder()` at startup. **Typical layout of the assets folder** ``` assets/ +-- fonts/ | +-- DroidSans.ttf # Default fonts used by HelloImGui to | +-- fontawesome-webfont.ttf # improve text rendering (esp. on High DPI) | | # if absent, a default LowRes font is used. | | | +-- Roboto/ # Optional: fonts for markdown | +-- LICENSE.txt | +-- Roboto-Bold.ttf | +-- Roboto-BoldItalic.ttf | +-- Roboto-Regular.ttf | +-- Roboto-RegularItalic.ttf | +-- Inconsolata-Medium.ttf +-- images/ +-- markdown_broken_image.png # Optional: used for markdown +-- world.png # Add anything in the assets folder! ``` Note: in C++, the assets folder also contains an `app_settings` folder, which contains application settings and app icons for different platforms. This is not needed / not available in Python applications. **Where to find the default assets** You can [download the default assets as a zip file](https://imgui-bundle.pages.dev/resources/assets.zip). Look at the folder [imgui_bundle/bindings/imgui_bundle/assets](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/assets) to see its content. ## Fonts and images Fonts are loaded in the `load_additional_fonts` callback, with paths relative to the assets folder: ```python from imgui_bundle import hello_imgui def load_fonts(): # Load a font at 18px size hello_imgui.load_font("fonts/Roboto-Regular.ttf", 18.0) # Load with options (e.g., merge icons into previous font) font_params = hello_imgui.FontLoadingParams() font_params.merge_to_last_font = True hello_imgui.load_font("fonts/icons.ttf", 16.0, font_params) params = hello_imgui.RunnerParams() params.callbacks.load_additional_fonts = load_fonts ``` Images are displayed from their path in the assets folder: ```python from imgui_bundle import hello_imgui, imgui def gui(): # Load and display an image from assets hello_imgui.image_from_asset("images/logo.png", imgui.ImVec2(100, 100)) # Or with its texture, e.g. for imgui.image() (which takes an ImTextureRef) texture = hello_imgui.im_texture_id_from_asset("images/logo.png") imgui.image(imgui.ImTextureRef(texture), imgui.ImVec2(100, 100)) ``` ## Troubleshooting **"Assets not found" or missing fonts/images:** 1. Ensure the `assets/` folder is in the same directory as your script 2. If running from a different directory, set the path explicitly: ```python from imgui_bundle import hello_imgui hello_imgui.set_assets_folder("/path/to/your/assets") ``` 3. For packaged applications, ensure assets are included in your distribution -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/pure-python-backend/ # Pure Python Backends Pure Python backends in ImGui Bundle let you use ImGui with Python-only windowing and rendering libraries instead of the default C++ GLFW+OpenGL backend. This gives you full control over the application loop but requires manual setup of windowing, input handling, and rendering. **Key Differences** * No Hello ImGui features: Pure Python backends don't provide DPI handling, themes, asset management, or other Hello ImGui conveniences * Manual setup required: You must handle window creation, input events, and the render loop yourself * Texture handling: Backends must implement support for dynamic fonts (ImGui 1.92+) [python_backends](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/python_backends) contains pure python backends for glfw, pyglet, pygame, sdl2 and sdl3. They do not offer the same DPI handling as HelloImGui, but they are a good starting point if you want to use alternative backends. See [examples](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/python_backends/examples) where you will find: * example_python_backend_glfw3.py * example_python_backend_pygame.py * example_python_backend_pyglet.py * example_python_backend_sdl2.py * example_python_backend_sdl3.py * example_python_backend_wgpu.py Note: Some other python libraries also provide ImGui integration, using Dear ImGui Bundle. See for example: * [wgpu-py](https://github.com/pygfx/wgpu-py/blob/main/examples/imgui_basic_example.py) * [moderngl-window](https://github.com/moderngl/moderngl-window/blob/master/examples/integration_imgui.py) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-async/ # Async Support _(Since v1.92.6)_ ImGui Bundle provides async/await support that enables **true parallel execution** of Python code alongside GUI rendering. This allows your Python computations to run at full speed while the GUI remains responsive. _Note: an async execution mode is also available for Jupyter notebooks; see [Notebook Usage](https://imgui-bundle.pages.dev/doc/python/notebook-runners/) for details._ ## Overview `immapp.run_async()` and `hello_imgui.run_async()` function allows you to run ImGui applications asynchronously using Python's `asyncio` framework. This is particularly useful when: - You need to perform computations while the GUI is running - You're building data visualization dashboards with live updates - You want to integrate ImGui into async Python applications - You're working in Jupyter notebooks (see [Notebook Usage](https://imgui-bundle.pages.dev/doc/python/notebook-runners/)) ## Quick Example Here's a simple example showing parallel execution: ```python import asyncio import time from imgui_bundle import immapp, imgui, hello_imgui GUI_FINISHED = False COMPUTATION_COUNT = 0 START_TIME = time.time() def gui(): params = hello_imgui.get_runner_params() idling_params = params.fps_idling idling_params.fps_idling_mode = hello_imgui.FpsIdlingMode.early_return idling_params.vsync_to_monitor = False idling_params.fps_max = 60.0 imgui.text(f"GUI FPS: {hello_imgui.frame_rate():.1f}") imgui.text(f"Computations per second: {COMPUTATION_COUNT / (time.time() - START_TIME):.1f}") global GUI_FINISHED GUI_FINISHED = hello_imgui.get_runner_params().app_shall_exit async def python_computation_loop(): """Run computations while GUI is active.""" """Python code which runs in parallel with the GUI!""" global COMPUTATION_COUNT while not GUI_FINISHED: _ = sum(range(1000)) # Do some work COMPUTATION_COUNT += 1 await asyncio.sleep(0) # Yield to event loop (required for async cooperation) async def main(): # Start GUI as an asyncio task (non-blocking) _gui_task = asyncio.create_task(immapp.run_async(gui, window_size_auto=True)) # Run computations in parallel await python_computation_loop() if __name__ == "__main__": asyncio.run(main()) ``` Also see [`demos_python_specifics/demo_run_async.py`](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_python_specifics/demo_run_async.py) ## Automatic FPS Optimization `immapp.run_async` automatically adjusts FPS idling parameters to optimize performance, so that the Python loop can run at maximum speed. The settings below are applied automatically by `immapp.run_async` to ensure that the GUI rendering returns early to Python instead of sleeping, allowing maximum parallelism between GUI rendering and Python code execution: ```python runner_params.fps_idling.fps_idling_mode = hello_imgui.FpsIdlingMode.early_return runner_params.fps_idling.vsync_to_monitor = False runner_params.fps_idling.fps_max = 60.0 ``` ## Signature Patterns `run_async()` supports two different ways to configure your application: ### 1. Simple GUI Function ```python async def gui(): imgui.text("Hello, World!") if imgui.button("Click me"): print("Button clicked!") await immapp.run_async( gui, window_title="My App", window_size_auto=True, top_most=True, # Optional addons (immapp only) with_implot=True, with_markdown=True ) ``` ### 2. Full RunnerParams (Maximum Control) ```python from imgui_bundle import hello_imgui, immapp runner_params = hello_imgui.RunnerParams() runner_params.callbacks.show_gui = gui runner_params.app_window_params.window_title = "My App" runner_params.imgui_window_params.show_menu_bar = True # With immapp, you can use AddOnsParams addons = immapp.AddOnsParams() addons.with_implot = True addons.with_node_editor = True asyncio.run(immapp.run_async(runner_params, addons)) ``` ## Yielding to the Event Loop In your async code, you **must** regularly yield control to the event loop to allow the GUI to render: ```python async def my_computation(): while condition: # Do some work result = expensive_computation() # Yield to allow GUI rendering (critical!) await asyncio.sleep(0) ``` Without `await asyncio.sleep(0)`, the GUI will freeze because asyncio can't switch between tasks. ## In the browser The same code runs in the browser, with [Pyodide](https://pyodide.org), whose event loop is the browser's: - Start the app with `asyncio.ensure_future(main())`: `asyncio.run()` fails there, an event loop runs already. - Yield with a short sleep (e.g. `await asyncio.sleep(0.02)`), after a slice of work: the browser draws the page only while Python sleeps, and `await asyncio.sleep(0)` would freeze it. The demo `demo_run_async.py` does both (it runs in the [playground](https://imgui-bundle.pages.dev/playground/?demo=demo_run_async.py)). ## Downloads that do not block the GUI `immapp.start_download()` starts an HTTP request in the background, from a GUI function. It works with `immapp.run` and `immapp.run_async`, on the desktop (in a thread) and in the browser (with a fetch). Look at the result's `done` at each frame: ```python from imgui_bundle import imgui, immapp download: immapp.Download | None = None data, error = b"", "" def gui() -> None: global download, data, error if imgui.button("Download"): download = immapp.start_download("https://example.com/data.json") if download is not None and download.done: data, error = download.data, download.error download = None if download is not None: imgui.text("Downloading...") elif error: imgui.text(error) immapp.run(gui) ``` - `error` is empty on success. Otherwise it gives the HTTP status and the start of the body, where web APIs explain their errors (`HTTP 429 Too Many Requests: ...`), or the network failure. - `status` gives the HTTP status, and `data` the body, also with an error status. - `method="POST"` with `json_body=...` sends JSON. `timeout_s` (30 s by default) limits the wait for the answer. - `headers={...}` adds HTTP headers, e.g. an API key: `{"Authorization": "Bearer "}`. - `immapp.download_url_bytes()` waits until the data is there: fine in a script, but it freezes a GUI meanwhile. ## Troubleshooting ### GUI Freezes **Problem**: The GUI becomes unresponsive during computations. **Solution**: Make sure to `await asyncio.sleep(0)` regularly in your computation loops. ### Exceptions in the async GUI If your GUI raises an exception, it might be difficult to trace with the GUI is running in an async way. In that case, it is recommended to first test your GUI in blocking mode using `immapp.run`, which will propagate exceptions normally. Once your GUI works in blocking mode, you can then switch to non-blocking mode (`immapp.run_async`). -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/notebook-runners/ # Jupyter Notebook support # Introduction The notebook submodules (`immapp.nb` and `hello_imgui.nb`) provide convenient functions for the usage in a local jupyter notebook, with two main modes: * **blocking mode**: other cells cannot be run in parallel. A screenshot is displayed after the application exits. * **non-blocking mode**: other cells can be run in parallel. The application window updates live. Note: _Note: Working on a remote notebook (or via Google Collab) may not work, since it requires a local X11 server (it might work if using X11 formwarding)._ # Blocking mode ## API `immapp.nb.run` and `hello_imgui.nb.run` functions will run a GUI application, wait for it to exit, and display a screenshot of the final application screen in the cell output. _During the application execution, other cells cannot be run._ **Parameters** `immapp.nb.run` and `hello_imgui.nb.run` accept the same parameters as `immapp.run` and `hello_imgui.run`, respectively. Optional additional parameters to controls the screenshot size (choose only one of the two): * thumbnail_ratio: (default=1.0) You can use it to change the size of the thumbnail. Passing 0.5 will create a thumbnail half the width of the window. * thumbnail_height: (default=0) You can use it to set a fixed height for the thumbnail (in pixels). If 0, the height is computed from the app window size. ## Example The example cell below demonstrates the blocking mode using `immapp.nb.run`. It shows a sinusoidal curve that can be adjusted with a slider. After closing the application window, a screenshot of the final state is displayed in the cell output. ```python from imgui_bundle import implot, immapp, imgui import numpy as np FREQ = 0.1 def gui(): global FREQ _, FREQ = imgui.slider_float("Frequency", FREQ, 0.01, 1.0) x = np.arange(0, 100, 0.1) y = np.sin(FREQ * x) if implot.begin_plot("My plot"): implot.plot_line("Sine wave", y) implot.end_plot() immapp.nb.run(gui, window_size=(600, 350), with_implot=True, thumbnail_height=500) ``` # Non blocking mode _(Since v1.92.6)_ ## API ### start * `immapp.nb.start` and `hello_imgui.nb.start` will run a GUI application, display it in a top-most window on top of the browser. **Other cells can be run while the application is running. The application window will update live.** _Note: these function return an `asyncio.Task`, which may be awaited or managed using asyncio._ **Parameters** `immapp.nb.start` and `hello_imgui.nb.start` accept the same parameters as `immapp.start` and `hello_imgui.start`, respectively. Optional additional parameter: `top_most` to control if the application window should stay on top of other windows. ### is_running * `immapp.nb.is_running` and `hello_imgui.nb.is_running` return True if the application is running, False otherwise. ### stop * `immapp.nb.stop` and `hello_imgui.nb.stop` will stop the running application. Tip: Only one application can be run at a time from a notebook. Trying to start a new application while another one is running will exit the previous one. _Note: If other cells are running while the application is running, they should call `await asyncio.sleep(0)` periodically to allow the application to update._ Important: If your GUI raises an exception, it might be difficult to trace with the GUI is running in an async way. In that case, it is recommended to first test your GUI in blocking mode using `immapp.nb.run`, which will propagate exceptions normally. Once your GUI works in blocking mode, you can then switch to non-blocking mode (`immapp.nb.start`). ## Example ### Start the application The cell below demonstrates the non-blocking mode using `immapp.nb.start`. It runs the same application as before (a sinusoidal curve that can be adjusted with a slider). You can modify the frequency while the application is running by changing the value of the `FREQ` variable in another cell. When you run it, the cell exits immediately, but the GUI application continues to show and to be interactive (you can then run other cells while the application is running). _Note: since, `immapp.nb.start` returns an `asyncio.Task`, you can see that the cell output shows the task information (Task pending, ...)._ Important: In a non-blocking mode, the GUI will not be shown inside the notebook (not even as a screenshot). Instead, it will be displayed in a separate top-most window on top of the browser. Refer to the "video demonstration" below for a demo of how the cells below will render on your screen. ```python immapp.nb.start(gui, window_size=(500, 300), with_implot=True, top_most=True) ``` ### Interact while the application is running The cell below shows that it is possible to modify the frequency via code while the application is running, and the curve updates live. ```python FREQ = 0.5 # Modify frequency while the app is running ``` ### Check if the application is running The cells below can be used to check if the application is running ```python immapp.nb.is_running() ``` ### Stop the application ```python immapp.nb.stop() ``` ### Video demonstration Demonstration of the non-blocking mode in a Jupyter notebook. # Example: Real-Time Data Stream Simulation This example simulates a **live data stream** that continuously updates, like you might see in a monitoring dashboard or during ML training. Tip: Refer to the "video demonstration" below for a demo of how the cells below will render on your screen. ## Start the GUI The cell below instantiate the application data (stream_data) and starts a GUI application that displays the live data stream. ```python from imgui_bundle import immapp, imgui, hello_imgui, implot import numpy as np import time # Streaming data buffer stream_data = { "values": [], "max_points": 500, "paused": False } def streaming_gui(): """GUI that shows a live streaming plot""" imgui.text("Live Data Stream") imgui.text(f"Points: {len(stream_data['values'])}") # Control buttons if imgui.button("Pause" if not stream_data["paused"] else "Resume"): stream_data["paused"] = not stream_data["paused"] imgui.same_line() if imgui.button("Clear"): stream_data["values"].clear() imgui.separator() # Plot the streaming data if len(stream_data["values"]) > 0: if implot.begin_plot("Data Stream", hello_imgui.em_to_vec2(40, 15)): x_data = np.arange(len(stream_data["values"]), dtype=np.float32) y_data = np.array(stream_data["values"], dtype=np.float32) implot.setup_axes("x", "y", implot.AxisFlags_.auto_fit, implot.AxisFlags_.auto_fit) implot.plot_line("Value", x_data, y_data) implot.end_plot() if imgui.button("Close"): hello_imgui.get_runner_params().app_shall_exit = True # Start streaming GUI (note: immapp.nb.start is non-blocking # and immediately returns an asyncio task) immapp.nb.start( streaming_gui, window_title="Data Stream Demo", window_size=(800, 400), with_implot=True, top_most=True ) print("✓ Streaming GUI started!") print("✓ Run the next cell to start the data stream.") ``` ## Simulate Data Stream The cell below simulates a data stream: this will add data points while the GUI displays them in real-time. * The GUI is already running above (in an asyncio task) * So, we define another asyncio task to add data points (stream_data_loop below), and we run it in async way. This cell will run for 5 seconds: while it runs, you should see the GUI updating live with new data points. Important: It is important to call periodically `await asyncio.sleep(...)` in the loop, to yield control to the event loop, so that the GUI can update. You may sleep for 0 seconds if you want to yield control with the shortest possible delay. (in the example below, we sleep for 0.001 seconds to simulate a 100 Hz data stream). ```python # import time import random import asyncio async def stream_data_loop(): print("Starting data stream... (will run for 10 seconds)") start_time = time.time() while time.time() - start_time < 5 and immapp.nb.is_running(): if not stream_data["paused"]: # Add new data point new_value = np.sin(time.time()) + random.gauss(0, 0.1) stream_data["values"].append(new_value) # Keep buffer size limited if len(stream_data["values"]) > stream_data["max_points"]: stream_data["values"].pop(0) await asyncio.sleep(0.01) # Yield control to the event loop print(f"✓ Stream finished. Final count: {len(stream_data['values'])} points") # Run the streaming loop await stream_data_loop() ``` ## Video demonstration Demonstration of the real-time data stream simulation in a Jupyter notebook. # Example: Real-Time AI Training and tuning **Video demonstration on youtube** https://www.youtube.com/embed/VqLz5F_bk60 Real-Time AI Training and tuning with Dear ImGui Bundle in Jupyter Notebooks **Links to notebooks** * [notebook_ml_training_async.ipynb](https://github.com/pthom/imgui_bundle/blob/main/docs/book/python/notebook_ml_training_async.ipynb) * [notebook_ml_training_threaded.ipynb](https://github.com/pthom/imgui_bundle/blob/main/docs/book/python/notebook_ml_training_threaded.ipynb) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-terminal/ # Terminal Emulator Widget `imgui_bundle.imgui_terminal` (Python only) embeds a terminal emulator in your ImGui application: a real shell rendered as an ImGui widget, with colors, scrollback, text selection, and job control. A zsh shell running inside an ImGui child window. **Install** ```bash pip install "imgui-bundle[terminal]" # adds the pyte VT100 emulator ``` **Quick start** ```python from imgui_bundle import hello_imgui, imgui_ctx, immapp from imgui_bundle.imgui_terminal import TerminalView, LocalShellTransport mono_font = None view = TerminalView() LocalShellTransport().start(view) # spawns $SHELL behind a pty (POSIX) def load_fonts(): global mono_font mono_font = hello_imgui.load_font("fonts/Inconsolata-Medium.ttf", 16.0) def gui(): with imgui_ctx.push_font(mono_font, 0.0): # the widget uses the active font view.render_in_child("terminal") params = hello_imgui.RunnerParams() params.callbacks.load_additional_fonts = load_fonts params.callbacks.show_gui = gui immapp.run(params) ``` Full demo: [demo_terminal_pyte.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_terminal/demo_terminal_pyte.py), also available in the Widgets tab of the demo explorer. ## Architecture: widget vs transport The module separates the *widget* from the *byte source*: ``` keyboard -> ImGui -> transport -> shell/remote -> view.feed -> pyte -> ImGui draws it ``` * **`TerminalView`** owns a [pyte](https://github.com/selectel/pyte) VT100 screen, draws it, and translates keyboard/mouse input. It knows nothing about where bytes come from: push output in with `view.feed(bytes)`, receive keystrokes via the `view.on_input` callback. `feed()` may be called from any thread, and asks for the next frames (`hello_imgui.request_refresh()`): the app does not idle while output streams in. * A **transport** produces and consumes those bytes. `LocalShellTransport` runs a local shell behind a pseudo-terminal (macOS / Linux). Any object with `start(view)` / `stop()` works (`TerminalTransport` protocol); `start()` takes ownership of `view.on_input` / `view.on_resize`. ### Remote shell (SSH, websocket, robot companion computer...) The same widget drives a remote shell: wire the callbacks to your channel and feed incoming bytes. ```python view = TerminalView() view.on_input = lambda data: channel.send(data) # keystrokes -> remote view.on_resize = lambda cols, rows: channel.resize(cols, rows) # in a background reader: for chunk in channel: view.feed(chunk) ``` When your reader thread changes what the GUI shows (connected, closed, an error), it calls `hello_imgui.request_refresh()`, so that the app shows it at once, even while it idles. Runnable remote demos (in `demos_python/demos_terminal/`): * [demo_terminal_ssh.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_terminal/demo_terminal_ssh.py) — over an SSH channel (paramiko) * [demo_terminal_websocket.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_terminal/demo_terminal_websocket.py) + [pty_bridge_server.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_terminal/pty_bridge_server.py) — over a websocket to a host-side shell bridge This websocket path is also how a **Pyodide / browser** build would work: there is no local pty in the browser, but the widget itself is pure Python and drives a remote shell over a websocket. ## Features * ANSI / 256-color / truecolor rendering; interactive programs work (`vim`, `htop`, `tmux`, shells with completion) * Scrollback with a native ImGui scrollbar; follows live output until you scroll up, typing snaps back * Full keyboard: F-keys, Ctrl combos incl. job control (Ctrl-C / Ctrl-Z), Alt as Meta, Shift-Tab, and modifier-encoded arrows/Home/End (Ctrl/Alt-Left/Right for word jumps) * Text selection: drag, double-click a word, triple-click a line, or click + shift-click across scrollback; copy with Cmd-C/V (macOS) or Ctrl-Shift-C/V, paste with right-click * ANSI colors plus bold and underline * Colors themable via `TerminalTheme`; the program-set window title is available as `view.title` ## Limitations pyte is a solid VT100 emulator, not a complete xterm. Known gaps: no alternate screen buffer (full-screen apps leave their frames in scrollback), no application cursor keys mode, no bracketed paste, no mouse reporting to programs, and double-width (CJK/emoji) glyphs may overlap. Glyphs missing from your font render as replacement boxes (ImGui does no OS font fallback); use a well-covered monospace font. The local-shell transport is POSIX only; on Windows, adapt it with [pywinpty](https://github.com/andfoy/pywinpty) (ConPTY) or use a remote transport. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-pyodide/ # Deploy to the web - Pyodide Dear ImGui Bundle applications can be effortlessly deployed to the web using Pyodide, enabling Python code to run directly in web browsers. This capability allows developers to share interactive GUI applications without requiring users to install any software. > **Note:** Pyodide cannot use large native packages (like TensorFlow or PyTorch), and initial loading can be slow. ## Pyodide Minimal Template With Pyodide, web deployment is as easy as copying the HTML template below. The Python code is unchanged from what you'd use for desktop. * [HTML template source](https://imgui-bundle.pages.dev/min_pyodide_app/demo_heart.source.txt) * [HTML template (run it)](https://imgui-bundle.pages.dev/min_pyodide_app/demo_heart) Important: The HTML file must be served through a local web server (e.g. `python -m http.server`). Opening it directly via `file://` prevents package loading. ### How it works The [template](https://imgui-bundle.pages.dev/min_pyodide_app/demo_heart.source.txt) is organised into four clearly marked parts. **Part 1 — Load Pyodide from a CDN** Pyodide is a Python interpreter compiled to WebAssembly; it runs directly in the browser. ```html ``` Check [pyodide latest releases](https://github.com/pyodide/pyodide/releases) and update the URL accordingly. **Part 2 — Python application code** The Python code is embedded in a ` ``` Alternative: keep the Python in a separate file (e.g. `app.py`) and fetch it at runtime — see Part 4 below. **Part 3 — Page DOM + styles** A `` (where the ImGui app draws) and a full-screen loader overlay with a pure-CSS spinner (shown while Pyodide and the wheel download). **Part 4 — JavaScript driver** Loads Pyodide, wires SDL to the canvas, installs `imgui_bundle` via micropip, then runs the Python code: ```javascript async function main() { const sdl2Canvas = document.getElementById("canvas"); sdl2Canvas.addEventListener('contextmenu', e => e.preventDefault()); // Load Pyodide let pyodide = await loadPyodide(); // Setup SDL, cf https://pyodide.org/en/stable/usage/sdl.html pyodide.canvas.setCanvas2D(sdl2Canvas); pyodide._api._skip_unwind_fatal_error = true; // Prepare micropip await pyodide.loadPackage("micropip"); const micropip = pyodide.pyimport("micropip"); // Install imgui_bundle (two options) // ---------------------------------- // // Option a (default): install from PyPI // (imgui_bundle publishes browser-compatible wheels on PyPI, cf PEP 783) await micropip.install('imgui-bundle'); // // Option b: use a wheel that is stored on your server, e.g. to pin a // version or work without PyPI access // (download a pyemscripten wheel from https://pypi.org/project/imgui-bundle/#files ) // await micropip.install('local_wheels/imgui_bundle-1.93.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl'); // Load additional required packages await micropip.install('numpy'); // Run the Python code // Option a (default): embedded in Part 2 pyodide.runPython(document.getElementById("pythonCode").textContent); // Option b: load from an external file // pyodide.runPython(await (await fetch('app.py')).text()); } main(); ``` For this, you will need to download the latest imgui-bundle pyodide wheel. Place it beside your html file (or in a `local_wheels/` subfolder, such as in the example). Download the wheel from [https://imgui-bundle.pages.dev/local_wheels/](https://imgui-bundle.pages.dev/local_wheels/) ## Pyodide API In Pyodide (browser environment), `run()` behaves differently than on desktop: it starts the GUI and **returns immediately** (fire-and-forget), since browsers cannot block. ### Pattern 1: Fire-and-Forget with run() (Recommended) The simplest pattern - same code as desktop, just works: ```python from imgui_bundle import imgui, immapp def gui(): imgui.text("Hello from Pyodide!") if imgui.button("Exit"): from imgui_bundle import hello_imgui hello_imgui.get_runner_params().app_shall_exit = True # In Pyodide: starts the GUI and returns immediately # On desktop: blocks until GUI closes immapp.run(gui, window_title="My App") ``` **This is perfect when:** - You want the same code to work on desktop and in browser - You don't need to do anything after the GUI closes - You want the simplest possible code *Note: In Pyodide, `run()` returns immediately. Use `run_async()` if you need to wait for the GUI to exit.* The frames are rendered by an asyncio task, which waits for each animation frame. An asyncio loop of your own that never waits (`await asyncio.sleep(0)` in a tight loop) competes with the frames and halves the frame rate: wait on a timer or on I/O instead. The [test engine](https://imgui-bundle.pages.dev/doc/core-libs/test-engine/) runs in the browser too (it needs JSPI: Chrome 137, Firefox 153, Safari 27). ### Pattern 2: Async Control with run_async() _(since v1.92.6)_ For workflows that need to wait for the GUI to exit: ```python import asyncio from imgui_bundle import imgui, immapp def gui(): imgui.text("Advanced async control") async def main(): # Wait for GUI to exit before continuing await immapp.run_async(gui, window_title="My App") print("GUI closed") asyncio.create_task(main()) ``` **Use this when:** - You need to know when the GUI exits - You're integrating with other async code - You want to run sequential GUI sessions ## Online Python playground With [this online playground](https://imgui-bundle.pages.dev/playground/), you can edit and run imgui apps in the browser, without installing anything. A browser window showing the playground: to the right an interactive demo of the butterfly effect using a 3D plot, and to the left the python code that creates it. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/python-tips/ # Tips # Context Managers In Python, the module imgui_ctx provides a lot of context managers that automatically call imgui.end(), imgui.end_child(), etc., when the context is exited, so that you can write: ```python from imgui_bundle import imgui, imgui_ctx with imgui_ctx.begin("My Window"): # imgui.end() called automatically imgui.text("Hello World") ``` Of course, you can choose to use the standard API by using the module imgui: ``` imgui.begin("My Window") imgui.text("Hello World") imgui.end() ``` * See [imgui_ctx](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_ctx.py) * See [demo_python_context_manager.py](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/demos_python/demos_python_specifics/demo_python_context_manager.py) # Advanced glfw callbacks When using the glfw backend, you can set advanced callbacks on all glfw events. Below is an example that triggers a callback whenever the window size is changed: ```python from imgui_bundle import glfw_utils, hello_imgui, imgui # import glfw # if you import glfw, do it _after_ imgui_bundle # define a callback def my_window_size_callback(window: glfw._GLFWwindow, w: int, h: int): print(f"Window size changed to {w}x{h}") def install_glfw_callbacks(): # Get the glfw window used by hello imgui glfw_win = glfw_utils.glfw_window_hello_imgui() glfw_utils.glfw.set_window_size_callback(glfw_win, my_window_size_callback) # Install the callback once everything is initialized, for example: runner_params = hello_imgui.RunnerParams() # ... runner_params.callbacks.post_init = install_glfw_callbacks ``` Important: Caution It is important to import glfw after imgui_bundle, since - upon import - imgui_bundle informs glfw that it shall use its own version of the glfw dynamic library. # Display Matplotlib plots in ImGui [imgui_fig.py](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/imgui_fig.py) is a small utility to display Matplotlib plots in ImGui. See [demo_matplotlib.py](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/demos_python/demos_python_specifics/plotting/demo_matplotlib.py) for an example. # Read the libraries doc as a Python developer ## General advices ImGui is a C++ library that was ported to Python. In order to work with it, you will often refer to its manual, which shows example code in C++. In order to translate from C++ to Python: 1. Change the function names and parameters' names from CamelCase to snake_case 2. Change the way the output are handled. a. in C++ ImGui::RadioButton modifies its second parameter (which is passed by address) and returns true if the user clicked the radio button. b. In python, the (possibly modified) value is transmitted via the return: imgui.radio_button returns a Tuple[bool, str] which contains (user_clicked, new_value). 3. if porting some code that uses static variables, use the `@immapp.static` decorator. In this case, this decorator simply adds a variable value at the function scope. It is preserved between calls. Normally, this variable should be accessed via demo_radio_button.value, however the first line of the function adds a synonym named static for more clarity. Do not overuse them! Static variable suffer from almost the same shortcomings as global variables, so you should prefer to modify an application state. **Example** C++ ```cpp void DemoRadioButton() { static int value = 0; ImGui::RadioButton("radio a", &value, 0); ImGui::SameLine(); ImGui::RadioButton("radio b", &value, 1); ImGui::SameLine(); ImGui::RadioButton("radio c", &value, 2); } ``` Python ```python @immapp.static(value=0) def demo_radio_button(): static = demo_radio_button clicked, static.value = imgui.radio_button("radio a", static.value, 0) imgui.same_line() clicked, static.value = imgui.radio_button("radio b", static.value, 1) imgui.same_line() clicked, static.value = imgui.radio_button("radio c", static.value, 2) ``` ## Enums and TextInput In the example below, two differences are important: **InputText functions:** `imgui.input_text` (Python) is equivalent to `ImGui::InputText` (C++) * In C++, it uses two parameters for the text: the text pointer, and its length. * In Python, you can simply pass a string, and get back its modified value in the returned tuple. **Enums handling:** * `ImGuiInputTextFlags_` (C++) corresponds to `imgui.InputTextFlags_` (python) and it is an enum (note the trailing underscore). * `ImGuiInputTextFlags` (C++) corresponds to `imgui.InputTextFlags` (python) and it is an int (note: no trailing underscore) You will find many similar enums. The dichotomy between int and enums, enables you to write flags that are a combinations of values from the enum (see example below). **Example** C++ ```cpp void DemoInputTextUpperCase() { static char text[64] = ""; ImGuiInputTextFlags flags = ( ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank ); /*bool changed = */ ImGui::InputText("Upper case, no spaces", text, 64, flags); } ``` Python ```python @immapp.static(text="") def demo_input_text_decimal() -> None: static = demo_input_text_decimal flags:imgui.InputTextFlags = ( imgui.InputTextFlags_.chars_uppercase | imgui.InputTextFlags_.chars_no_blank ) changed, static.text = imgui.input_text("Upper case, no spaces", static.text, flags) ``` ## Dear ImGui C++ vs Python API Dear ImGui’s C++ API is thoroughly documented in its header files: * [main API](https://github.com/ocornut/imgui/blob/master/imgui.h) * [internal API](https://github.com/ocornut/imgui/blob/master/imgui_internal.h) The Dear ImGui Python API The python API closely mirrors the C++ API, and its documentation is extremely easy to access from your IDE, via thoroughly documented stub (*.pyi) files. * [main API](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui/__init__.pyi) * [internal API](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui/internal.pyi) # See Also - **[Dear ImGui Basics](https://imgui-bundle.pages.dev/doc/core-libs/imgui/)** – Widget concepts, IDs, common patterns - **[Hello ImGui & ImmApp](https://imgui-bundle.pages.dev/doc/core-libs/hello-imgui-immapp/)** – App runners, DPI handling, configuration - **[Async Support](https://imgui-bundle.pages.dev/doc/python/python-async/)** – Running GUI alongside async Python code - **[Jupyter Notebooks](https://imgui-bundle.pages.dev/doc/python/notebook-runners/)** – Using ImGui Bundle in notebooks -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/python/desktop-deploy/ # Desktop Deployment This page covers packaging Python applications built with Dear ImGui Bundle as standalone desktop executables. For this, you will need to use a packaging tool like **[PyInstaller](https://pyinstaller.org/)** to create an executable from your Python code. Other tools like [cx_Freeze](https://cx-freeze.readthedocs.io/) or [Nuitka](https://nuitka.net/) can also work. They will allow you to distribute your application without requiring users to install Python or dependencies. They will also allow you to set an app icon, which is important for a polished user experience. Using those packaging tools is known to work, but we do not provide official support for them. ## Icons: Window Icon vs App Icon There are two different types of icons: - **Window icon**: The icon shown in the window title bar and taskbar while the app is running. Works on Windows and Linux; on macOS, the window icon comes from the app bundle icon. - **App icon**: The icon of the executable file itself (shown in file explorers, app launchers, etc.). Requires a packaging tool like PyInstaller. ### Window Icon (Windows/Linux) Place your icon at `assets/app_settings/icon.png` and make sure the assets folder is set correctly: ```python from imgui_bundle import hello_imgui, immapp import os def main(): assets_path = os.path.join(os.path.dirname(__file__), "assets") hello_imgui.set_assets_folder(assets_path) # or hello_imgui.add_assets_search_path immapp.run(gui, window_title="My App") ``` **Icon requirements:** - Square, PNG format - At least 256x256 pixels (512x512 recommended) - Located at `/app_settings/icon.png` This sets the **window icon** on Windows and Linux. On macOS, window icons are the same as the app icon (see below). ### App Icon (packaged applications) In Python, you will need a packaging tool like **PyInstaller** to set the app icon when creating standalone executables. ## Packaging with PyInstaller It is best to refer to the [PyInstaller](https://pyinstaller.org/) documentation for details, but here are some key points: ### Example with macOS A complete macOS example is available in the repository: [demo_packaging/macos](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/demos_python/demo_packaging/macos) ### For windows For windows, you could create a spec file like this: ``` # yourapp.spec a = Analysis( ['your_app.py'], datas=[("assets", "assets")], # Include assets folder # ... other settings ) exe = EXE( pyz, a.scripts, # ... other settings icon='path/to/your_icon.ico', # <-- Set app icon here (Windows uses . ico) ) ``` Then build with: ```bash pip install pyinstaller pyinstaller yourapp.spec ``` ## Packaging with Nuitka Instructions inspired by [neudinger's article](https://neudinger.medium.com/the-modern-c-python-gui-stack-from-native-binary-to-webassembly-cc235bf3fb3b) Nuitka is a Python compiler that can create standalone executables. It can be used to package Dear ImGui Bundle applications as well. The following command compiles `your_app.py` into a standalone executable, including the assets from Dear ImGui Bundle: ``` export imgui_bundle_asset_path=`python -c "import imgui_bundle, os; print(os.path.join(os.path.dirname(imgui_bundle.__file__), 'assets'))"` python -m nuitka \ --standalone \ --include-package=imgui_bundle \ --include-package-data=imgui_bundle \ --include-module=importlib.util \ --include-data-dir=${imgui_bundle_asset_path}=imgui_bundle/assets \ --noinclude-pytest-mode=nofollow \ --enable-plugin=no-qt \ -o your_app_compiled \ your_app.py ``` *Note: Nuitka provides an option "--onefile" to create a single executable, but this will slow the startup time. It is recommended to use the default "standalone" mode, which creates a folder with the executable and dependencies, for better performance.* Do read Nuitka's documentation for more details and options: https://nuitka.net/doc/user-manual.html -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/cpp/cpp-install/ # C++ Installation ## Integrate Dear ImGui Bundle in your own project in 5 minutes The easiest way to use Dear ImGui Bundle in an external project is to use the template available at https://github.com/pthom/imgui_bundle_template. This template includes everything you need to set up your own project. ## Build from source If you choose to clone this repo, follow these instructions: ```bash git clone https://github.com/pthom/imgui_bundle.git cd imgui_bundle git submodule update --init --recursive # (1) mkdir build cd build cmake .. make -j ``` (1) Since there are lots of submodules, this might take a few minutes Tip: ImmVision works out of the box without OpenCV, and never links it. If your application uses OpenCV, it can opt in to `cv::Mat` interop (header-only conversions) by defining `IMMVISION_HAS_OPENCV` and linking OpenCV by itself: ```cmake find_package(OpenCV REQUIRED) target_compile_definitions(my_app PRIVATE IMMVISION_HAS_OPENCV) target_link_libraries(my_app PRIVATE opencv_core) ``` Tip: There are lots of CMake options to customize the build. See [CMakeLists.txt](https://github.com/pthom/imgui_bundle/blob/main/CMakeLists.txt) ## Install as a CMake package Dear ImGui Bundle can be installed with `cmake --install`, and then used from another project with `find_package(imgui_bundle)` (this is also the basis for package managers such as Conan). The `cpp_package` preset builds the C++ libraries (without the demos) and installs them into `builds/cpp_package/install`: ```bash cmake --preset cpp_package cmake --build builds/cpp_package/build --config Release cmake --install builds/cpp_package/build --config Release ``` Then, in your project (see the [template](https://github.com/pthom/imgui_bundle_template) for a complete example): ```cmake find_package(imgui_bundle CONFIG REQUIRED) # cmake -DCMAKE_PREFIX_PATH=/path/to/imgui_bundle/builds/cpp_package/install imgui_bundle_add_app(my_app my_app.cpp) ``` (The template falls back to a local copy or to a download of imgui_bundle when no installed package is found; pass `-Dimgui_bundle_DIR=/path/to/install/lib/cmake/imgui_bundle` instead to require the installed package.) Note: Install into an empty prefix. When a library such as glfw or freetype is not found on the system, it is downloaded and installed along with the package; if you configure again while a previous install sits in the prefix, `find_package` would find those libraries there and take them for system libraries. The `cpp_package` preset prevents this by setting `CMAKE_FIND_NO_INSTALL_PREFIX=ON`; do the same if you configure by hand. ## Run the C++ demo If you built ImGuiBundle from source, Simply run build/bin/demo_imgui_bundle. The source for the demos can be found inside bindings/imgui_bundle/demos_cpp. Tip: Consider demo_imgui_bundle as a manual with lots of examples and related code source. It is always available online ## Multiplatform applications Hello ImGui and Dear ImGui Bundle offer excellent support for multiplatform applications (Windows, macOS, Linux, iOS, Android, and Emscripten). See this tutorial video for Hello ImGui: Tip: The principle with Dear ImGui Bundle is the same as described in the video, just use the dedicated [Dear ImGui Bundle project template](https://github.com/pthom/imgui_bundle_template), and use `imgui_bundle_add_app` in your CMakeLists.txt. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/cpp/cpp-assets/ # Assets folder (for C++) HelloImGui and ImmApp applications rely on the presence of an `assets/` folder. **This folder stores:** * Default fonts used by the markdown renderer (if the markdown addon is used). * All the resources (images, fonts, etc.) used by the application. Feel free to add any resources there! **Assets folder location** The assets folder should be placed in the same folder as the CMakeLists.txt for the application (the one calling imgui_bundle_add_app) **Typical layout of the assets folder** ``` assets/ +-- app_settings/ # Application settings | +-- icon.png # This will be the app icon, it should be square | | # and at least 256x256. It will be converted | | # to the right format, for each platform (except Android) | +-- apple/ | | +-- Info.plist # macOS and iOS app settings | | # (or Info.ios.plist + Info.macos.plist) | | | +-- android/ # Android app settings: files here will be deployed | | |-- AndroidManifest.xml # Optional manifest | | +-- res/ | | +-- mipmap-xxxhdpi/ # Optional icons for different resolutions | | +-- ... # Use Android Studio to generate them: | | # right click on res/ => New > Image Asset | +-- emscripten/ | |-- shell.emscripten.html # Emscripten shell file | | # (this file will be cmake "configured" | | # to add the name and favicon) | +-- custom.js # Any custom file here will be deployed | # in the emscripten build folder +-- fonts/ | +-- DroidSans.ttf # Default fonts used by HelloImGui to | +-- fontawesome-webfont.ttf # improve text rendering (esp. on High DPI) | | # if absent, a default LowRes font is used. | | | +-- Roboto/ # Optional: fonts for markdown | +-- LICENSE.txt | +-- Roboto-Bold.ttf | +-- Roboto-BoldItalic.ttf | +-- Roboto-Regular.ttf | +-- Roboto-RegularItalic.ttf | +-- Inconsolata-Medium.ttf +-- images/ +-- markdown_broken_image.png # Optional: used for markdown +-- world.png # Add anything in the assets folder! ``` **If needed, change the assets folder location:** Call `HelloImGui::SetAssetsFolder()` at startup. Or specify its location in CMake via `imgui_bundle_add_app(app_name file.cpp ASSETS_LOCATION "path/to/assets")`. **Where to find the default assets** You can [download the default assets as a zip file](https://imgui-bundle.pages.dev/resources/assets.zip). Look at the folder [imgui_bundle/bindings/imgui_bundle/assets](https://github.com/pthom/imgui_bundle/tree/main/bindings/imgui_bundle/assets) to see its content. -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/core-libs/imgui/ # Dear ImGui [Dear ImGui](https://github.com/ocornut/imgui) is the foundation of ImGui Bundle. It's a bloat-free graphical user interface library for C++ that outputs optimized vertex buffers for rendering. ## ImGui Manual The best way to learn Dear ImGui is through the interactive **ImGui Manual**: Link: https://pthom.github.io/imgui_explorer/ ImGui Manual - Interactive reference for Dear ImGui **[Launch the ImGui Manual](https://pthom.github.io/imgui_explorer)** The manual lets you: - Browse all ImGui widgets interactively - See the corresponding C++ and Python code - Copy code snippets directly ## Basic Usage Python: ```python from imgui_bundle import imgui, immapp value = 0.5 checked = False text = "Hello" def gui(): global value, checked, text imgui.text("Hello, world!") if imgui.button("Click me"): print("Button clicked!") changed, value = imgui.slider_float("Value", value, 0.0, 1.0) changed, checked = imgui.checkbox("Enable", checked) changed, text = imgui.input_text("Name", text) immapp.run(gui, window_title="ImGui Demo") ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui.h" float value = 0.5f; bool checked = false; char text[256] = "Hello"; void gui() { ImGui::Text("Hello, world!"); if (ImGui::Button("Click me")) { printf("Button clicked!\n"); } ImGui::SliderFloat("Value", &value, 0.0f, 1.0f); ImGui::Checkbox("Enable", &checked); ImGui::InputText("Name", text, sizeof(text)); } int main() { ImmApp::Run(gui, "ImGui Demo", {800, 600}); return 0; } ``` ## Key Concepts ### Immediate Mode ImGui uses an **immediate mode** paradigm: you call widget functions every frame, and they return whether they were interacted with. Python: ```python # The button returns True when clicked if imgui.button("Save"): save_file() # Sliders return (changed, new_value) changed, value = imgui.slider_float("Speed", value, 0.0, 100.0) if changed: update_speed(value) ``` C++: ```cpp // The button returns true when clicked if (ImGui::Button("Save")) { save_file(); } // Sliders modify the value in place if (ImGui::SliderFloat("Speed", &value, 0.0f, 100.0f)) { update_speed(value); } ``` ### Widget IDs ImGui identifies widgets by their label. You shall not have two widgets with the same label in the same scope. Either use `##` to add a hidden ID suffix: ```python imgui.button("OK") imgui.button("OK##dialog2") # Will be displayed as "Ok", but is different from "OK##dialog2" ``` Or add a scope using `push_id()`/`pop_id()`: ```python for i in range(3): imgui.push_id(i) imgui.button("Button") # IDs are "0/Button", "1/Button", "2/Button" imgui.pop_id() ``` ### Begin/End Pairs Many ImGui functions come in pairs: Python: ```python if imgui.begin_menu("File"): if imgui.menu_item_simple("Open"): open_file() # you should call `end_*` after `begin_*`, if the `begin_*` returned `True`. imgui.end_menu() # Note: begin() is an exception, always call end(), even if begin() returned False # begin() returns two values: (expanded, opened); opened is the state of the close button, if any # (begin_simple("My Window") returns expanded alone, for a window without a close button) expanded, _ = imgui.begin("My Window") if expanded: imgui.text("Content here") imgui.end() # Always call end! ``` C++: ```cpp if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("Open")) { open_file(); } ImGui::EndMenu(); } // Note: Begin() is an exception, always call End(), even if Begin() returned false if (ImGui::Begin("My Window")) { ImGui::Text("Content here"); } ImGui::End(); // Always call End! ``` Tip: Python users can use context managers for cleaner code: ```python from imgui_bundle import imgui, imgui_ctx with imgui_ctx.begin("My Window") as window_opened: if window_opened: imgui.text("Content here") # end() called automatically ``` ## Common Patterns ### App State Management Keep your application state outside the GUI function: ```python # Good: State in a class or module-level variables class AppState: counter = 0 name = "" state = AppState() def gui(): if imgui.button("Increment"): state.counter += 1 _, state.name = imgui.input_text("Name", state.name) ``` ### Conditional Widgets Remember that ImGui widgets only exist when rendered: ```python # Widget only exists when show_advanced is True if show_advanced: _, advanced_value = imgui.slider_float("Advanced", advanced_value, 0, 1) ``` ### Layout with same_line Use `same_line()` to place widgets horizontally: ```python imgui.button("One") imgui.same_line() imgui.button("Two") imgui.same_line() imgui.button("Three") ``` ### Horizontal and vertical layouts (StackLayout) The bundle's Dear ImGui includes StackLayout (by thedmd): `begin_horizontal()` / `end_horizontal()`, `begin_vertical()` / `end_vertical()`, and `spring()`, which takes the free space. Prefer it to `same_line()`: - for many items on one line; - for right-aligned or centered content, with `spring()`; - for flexible spacing between groups of widgets. Python: ```python imgui.begin_horizontal("toolbar", imgui.ImVec2(imgui.get_content_region_avail().x, 0.0)) imgui.button("Left") imgui.button("Also Left") imgui.spring() # pushes the next items to the right imgui.text("Right-aligned") imgui.end_horizontal() ``` C++: ```cpp ImGui::BeginHorizontal("toolbar", ImVec2(ImGui::GetContentRegionAvail().x, 0.f)); ImGui::Button("Left"); ImGui::Button("Also Left"); ImGui::Spring(); // pushes the next items to the right ImGui::Text("Right-aligned"); ImGui::EndHorizontal(); ``` - The size of a layout: 0 is automatic, a positive value is fixed, a negative value is relative to the far edge of the content region, as for other widgets (`-FLT_MIN` fills it). - A layout scopes its contents like `push_id()`. A popup opened inside a layout and begun after it needs an ID taken before the layout: `popup_id = imgui.get_id("popup")`, then `imgui.open_popup(popup_id)` inside, and `imgui.begin_popup("popup")` after the layout. ### DPI-Aware Sizing (Basic) Avoid hardcoded pixel sizes for portable UIs. Use sizes relative to the font: ```python font_size = imgui.get_font_size() imgui.button("Click", imgui.ImVec2(font_size * 8, font_size * 2)) ``` Tip: Prefer the more convenient `em_to_vec2()` function, available directly from `imgui_bundle`. See [DPI-Aware Sizing](https://imgui-bundle.pages.dev/doc/core-libs/hello-imgui-immapp/#dpi-aware-sizing). ## Documentation - **[ImGui Manual](https://pthom.github.io/imgui_explorer/)** - Interactive widget reference - **[Dear ImGui Repository](https://github.com/ocornut/imgui)** - Official repository with extensive documentation - **Python API Reference:** [imgui/\_\_init\_\_.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui/__init__.pyi), [imgui/internal.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui/internal.pyi) - **C++ API Reference:** [imgui.h](https://github.com/ocornut/imgui/blob/docking/imgui.h), [imgui_internal.h](https://github.com/ocornut/imgui/blob/docking/imgui_internal.h) - [Dear ImGui Support & FAQ](https://github.com/ocornut/imgui?tab=readme-ov-file#support-frequently-asked-questions-faq) ## See Also - **[Hello ImGui & ImmApp](https://imgui-bundle.pages.dev/doc/core-libs/hello-imgui-immapp/)** – App runners, window management, DPI handling - **[Python Tips](https://imgui-bundle.pages.dev/doc/python/python-tips/)** – Context managers, C++ to Python translation - **[Add-on Libraries](https://imgui-bundle.pages.dev/doc/addons/plotting/)** – ImPlot, ImmVision, node editors, and more -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/core-libs/hello-imgui-immapp/ # Hello ImGui - ImmApp **Hello ImGui** and **ImmApp** are the two main ways to create applications with ImGui Bundle. - **[Hello ImGui](https://github.com/pthom/hello_imgui)** is a cross-platform framework that handles window creation, backend initialization, assets, theming, and more. - **ImmApp** (Immediate App) is a thin wrapper around Hello ImGui that simplifies the initialization of add-ons (ImPlot, Markdown, Node Editor, etc.). These runners enable you to create powerful ImGui applications with minimal boilerplate code. Tip: * Use `hello_imgui.run()` for simple apps without add-ons. Use `immapp.run()` when you need add-ons like ImPlot or Markdown. * In Python, you may also choose to use [pure Python backends](https://imgui-bundle.pages.dev/doc/python/pure-python-backend/) for full control over windowing and rendering. Note: You may also choose to bypass these runners: use [pure python backends](https://imgui-bundle.pages.dev/doc/python/pure-python-backend/), or integrate Dear ImGui directly in your C++ code. ## Hello ImGui ### Quick Start Python: ```python from imgui_bundle import hello_imgui, imgui def gui(): imgui.text("Hello, world!") hello_imgui.run(gui, window_title="My App", window_size=(800, 600)) ``` C++: ```cpp #include "hello_imgui/hello_imgui.h" #include "imgui.h" void gui() { ImGui::Text("Hello, world!"); } int main() { HelloImGui::Run(gui, "My App", {800, 600}); return 0; } ``` ### Documentation - **[Hello ImGui Documentation](https://pthom.github.io/hello_imgui)** - Full documentation - **[RunnerParams Reference](https://pthom.github.io/hello_imgui/book/doc-params/)** - All configuration options - **[API Reference](https://pthom.github.io/hello_imgui/book/doc-api/)** - Full API documentation ### Configuration with RunnerParams For full control, configure your application via `RunnerParams`: Python: ```python from imgui_bundle import hello_imgui, imgui def gui(): imgui.text("Hello!") # Create and configure runner params params = hello_imgui.RunnerParams() params.app_window_params.window_title = "My Application" params.app_window_params.window_geometry.size = (1200, 800) params.app_window_params.restore_previous_geometry = True # ImGui window settings params.imgui_window_params.show_menu_bar = True params.imgui_window_params.show_status_bar = True # Set the GUI callback params.callbacks.show_gui = gui # Run hello_imgui.run(params) ``` C++: ```cpp #include "hello_imgui/hello_imgui.h" #include "imgui.h" void gui() { ImGui::Text("Hello!"); } int main() { HelloImGui::RunnerParams params; params.appWindowParams.windowTitle = "My Application"; params.appWindowParams.windowGeometry.size = {1200, 800}; params.appWindowParams.restorePreviousGeometry = true; params.imGuiWindowParams.showMenuBar = true; params.imGuiWindowParams.showStatusBar = true; params.callbacks.ShowGui = gui; HelloImGui::Run(params); return 0; } ``` See [RunnerParams Reference](https://pthom.github.io/hello_imgui/book/doc-params/) for all configuration options. For Python, see [RunnerParams Type Hints](https://github.com/pthom/imgui_bundle/blob/33f407b1d8083f88514d61e0b43683860b39fc96/bindings/imgui_bundle/hello_imgui.pyi#L2936) ### Callbacks Hello ImGui provides several callback hooks: | Callback | When Called | |----------|-------------| | `show_gui` | Every frame (main GUI) | | `show_menus` | Every frame (menu bar content) | | `show_status` | Every frame (status bar) | | `post_init` | Once, after OpenGL initialization | | `before_exit` | Once, before shutdown | See [Full Callback Reference](https://pthom.github.io/hello_imgui/book/doc-params/#runner-callbacks) for details. For Python, see [Callbacks Type Hints](https://github.com/pthom/imgui_bundle/blob/33f407b1d8083f88514d61e0b43683860b39fc96/bindings/imgui_bundle/hello_imgui.pyi#L1713). ### Application Settings ImGui applications store settings (window positions, etc.) in an INI file. By default, it's named after your window title. For production apps, use a proper config location: ```python params.ini_folder_type = hello_imgui.IniFolderType.app_user_config_folder # ~/.config or AppData params.ini_filename = "my_app/settings.ini" ``` You can also store custom settings: `hello_imgui.save_user_pref("key", "value")` / `load_user_pref("key")` ### DPI-Aware Sizing **Never use fixed pixel sizes.** This leads to portability issues on high-DPI screens. Instead, use sizes relative to the font size using "em" units. Hello ImGui provides helper functions: Tip: 1 em = the height of the current font. See [em (typography)](https://en.wikipedia.org/wiki/Em_(typography)). Python: ```python from imgui_bundle import imgui, em_to_vec2, em_size def gui(): # Button sized as 10em x 2em (scales with DPI) imgui.button("A button", em_to_vec2(10, 2)) # For single values, use em_size width = em_size(10) ``` C++: ```cpp #include "imgui.h" #include "hello_imgui/hello_imgui.h" void gui() { // Button sized as 10em x 2em (scales with DPI) ImGui::Button("A button", HelloImGui::EmToVec2(10, 2)); // For single values, use EmSize float width = HelloImGui::EmSize(10); } ``` Note: `em_to_vec2` and `em_size` are available: - Directly from `imgui_bundle` (Python, since v1.92.6: `from imgui_bundle import em_to_vec2`) - In the `hello_imgui` and `immapp` modules (Python) - In the `HelloImGui` and `ImmApp` namespaces (C++, as `EmToVec2` and `EmSize`) ### The mouse wheel in a page that scrolls Hello ImGui keeps the mouse wheel on the window it scrolls, as a browser does. A page scrolled with the wheel keeps scrolling when a plot or an image passes under the mouse, and the plot does not zoom. A wheel that starts on the plot zooms it. The page lets go of the wheel when the mouse moves, or 0.7 s after its last wheel event. A widget of your own that reads the wheel (a value changed by the wheel, a zoom) claims it while hovered, as ImPlot and ImmVision do. Without the claim, in a page that scrolls, the page takes the wheel and the widget never sees it. The option `wheel_session` of the runner params turns this off (C++: `runnerParams.wheelSession = false`): Dear ImGui's own behavior, where a plot that arrives under the mouse takes the wheel. Python: ```python imgui.invisible_button("zoom", em_to_vec2(10, 10)) if imgui.set_item_key_owner(imgui.Key.mouse_wheel_y): # hovered: the wheel is this widget's zoom *= 1.1 ** imgui.get_io().mouse_wheel ``` C++: ```cpp ImGui::InvisibleButton("zoom", HelloImGui::EmToVec2(10, 10)); if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY)) // hovered: the wheel is this widget's zoom *= powf(1.1f, ImGui::GetIO().MouseWheel); ``` --- ## ImmApp ImmApp handles add-on initialization automatically via simple boolean flags. ### Quick Start Python: ```python import numpy as np from imgui_bundle import immapp, imgui, implot, rich_md xs = np.array([1, 2, 3, 4], dtype=np.float64) # ImPlot takes numpy arrays ys = np.array([1, 4, 2, 3], dtype=np.float64) def gui(): rich_md.render("# Hello with Markdown!") if implot.begin_plot("My Plot"): implot.plot_line("data", xs, ys) implot.end_plot() # Enable add-ons with simple flags immapp.run( gui, window_title="My App", window_size=(800, 600), with_implot=True, with_markdown=True ) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui_rich_md/rich_md.h" #include "implot/implot.h" void gui() { RichMd::Render("# Hello with Markdown!"); if (ImPlot::BeginPlot("My Plot")) { double x[] = {1, 2, 3, 4}; double y[] = {1, 4, 2, 3}; ImPlot::PlotLine("data", x, y, 4); ImPlot::EndPlot(); } } int main() { HelloImGui::SimpleRunnerParams runnerParams; runnerParams.guiFunction = gui; runnerParams.windowSize = {800, 600}; ImmApp::AddOnsParams addons; addons.withImplot = true; addons.withMarkdown = true; ImmApp::Run(runnerParams, addons); return 0; } ``` ### Available Add-ons | Flag | Add-on | Description | |------|--------|-------------| | `with_implot` | ImPlot | 2D plotting | | `with_implot3d` | ImPlot3D | 3D plotting | | `with_markdown` | rich_md | Markdown rendering | | `with_node_editor` | imgui-node-editor | Node graphs | | `with_tex_inspect` | imgui_tex_inspect | Texture inspector | ### Full Configuration For advanced configuration, use `RunnerParams` (same as Hello ImGui) combined with `AddOnsParams`: ```python immapp.run(runner_params, addons) # Python ImmApp::Run(runnerParams, addons); // C++ ``` --- ## Usage examples and demonstrations Below are demonstrations from the ImGui Bundle Interactive Manual, showcasing various features of Hello ImGui and ImmApp. ### Docking Demo Link: https://imgui-bundle.pages.dev/explorer/demo_docking.html Docking Demo - Full-featured ImGui application with Hello ImGui [Docking Demo](https://imgui-bundle.pages.dev/explorer/demo_docking.html) shows how to create a full-featured application: - Complex app layout (with several possible layouts) - Load additional fonts, possibly colored, and with emojis - Display a status bar and log window - Customize the theme - User settings persistence The source code is heavily documented and can be used as a template for your own applications. Source code: [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_docking.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_docking.cpp) ### ImmApp - Launch an app with addons Link: https://imgui-bundle.pages.dev/explorer/demo_assets_addons.html ImmApp with add-ons: assets, markdown, and ImPlot Demonstrates how to use ImmApp with multiple add-ons: - Load and display assets (images, icons) - Render markdown content with rich_md - Display interactive plots with ImPlot Source code: [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_assets_addons.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_assets_addons.cpp) ### Custom 3D Background Link: https://imgui-bundle.pages.dev/explorer/demo_custom_background.html Custom 3D background with OpenGL shaders Demonstrates how to render a custom 3D background using OpenGL: - Use `runner_params.callbacks.custom_background` callback - Load and compile shaders - Adjust uniforms via the GUI Source code: [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_custom_background.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_custom_background.cpp) ### Power Save Mode Link: https://imgui-bundle.pages.dev/explorer/demo_powersave.html Demonstrates FPS idling to reduce CPU usage when the app is idle. Hello ImGui tries hard to save the CPU (and the battery): 3 seconds after the last user interaction, it lowers the frame rate to `fps_idle` (10 by default with `immapp.run`). Content that changes on its own (an animation, a live image, a plot of varying data) would then become choppy. Two calls keep it smooth: - `set_item_is_live()`, right after its widget: the app keeps its full speed while the widget is visible. - `request_refresh()`, from any thread, when new data arrives (a camera, a socket): the next frame comes at full speed. Python: ```python if implot.begin_plot("Live data"): implot.plot_line("signal", xs, ys) implot.end_plot() hello_imgui.set_item_is_live() # no idling while the plot is visible # In a thread that receives data: hello_imgui.request_refresh() ``` C++: ```cpp if (ImPlot::BeginPlot("Live data")) { ImPlot::PlotLine("signal", xs.data(), ys.data(), (int)xs.size()); ImPlot::EndPlot(); HelloImGui::SetItemIsLive(); // no idling while the plot is visible } // In a thread that receives data: HelloImGui::RequestRefresh(); ``` The idling settings are global: they act on the whole application. Prefer the calls above to keep some content moving. ```python immapp.run(gui, fps_idle=10.0) # the frame rate when idle (0: no idling) # Or while the app runs: fps_idling = hello_imgui.get_runner_params().fps_idling fps_idling.fps_idle = 10.0 fps_idling.enable_idling = False # no idling at all ``` In a browser, frames come at the display's rate: the idle frame rate is the nearest one it allows (on a 60 Hz display: 30, 20, 15...). * Demo: [Try online](https://imgui-bundle.pages.dev/explorer/demo_powersave.html) | * Source code: [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_powersave.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_powersave.cpp) ## Advanced - Manual Rendering For complete control over the render loop (useful for game engines or custom frameworks), use manual rendering instead of `run()`. Python: ```python from imgui_bundle import imgui, hello_imgui, immapp def gui(): imgui.text("Hello, ImGui Bundle!") # Setup runner_params = hello_imgui.RunnerParams() runner_params.callbacks.show_gui = gui addons = immapp.AddOnsParams() addons.with_implot = True immapp.manual_render.setup_from_runner_params(runner_params, addons) # Custom render loop while not hello_imgui.get_runner_params().app_shall_exit: immapp.manual_render.render() # Do other work here (physics, networking, etc.) # Cleanup immapp.manual_render.tear_down() ``` C++: ```cpp #include "imgui.h" #include "hello_imgui/hello_imgui.h" #include "immapp/immapp.h" int main() { // Setup HelloImGui::RunnerParams runnerParams; runnerParams.callbacks.ShowGui = []() { ImGui::Text("Hello, ImGui Bundle!"); }; ImmApp::AddOnsParams addons; addons.withImplot = true; ImmApp::ManualRender::SetupFromRunnerParams(runnerParams, addons); // Custom render loop while (!HelloImGui::GetRunnerParams()->appShallExit) { ImmApp::ManualRender::Render(); // Do other work here (physics, networking, etc.) } // Cleanup ImmApp::ManualRender::TearDown(); return 0; } ``` **Use cases:** game engine integration, heavy computation between frames, synchronizing with external systems, precise frame timing control. **Demo:** [Try online](https://imgui-bundle.pages.dev/explorer/demo_custom_background.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_custom_background.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_custom_background.cpp) --- ## See Also - **[Dear ImGui Basics](https://imgui-bundle.pages.dev/doc/core-libs/imgui/)** – Widget concepts, IDs, common patterns - **[ImGui Test Engine](https://imgui-bundle.pages.dev/doc/core-libs/test-engine/)** – Automated testing for ImGui apps - **[Add-on Libraries](https://imgui-bundle.pages.dev/doc/addons/plotting/)** – ImPlot, ImmVision, markdown, node editors -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/core-libs/test-engine/ # ImGui Test Engine [ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) is the official testing and automation framework for Dear ImGui. It enables automated UI testing, screenshot capture, and regression testing. Note: **License:** Free for individuals, educational, open-source, and small business uses. Larger businesses require a paid license. See the [full license](https://github.com/ocornut/imgui_test_engine/blob/main/imgui_test_engine/LICENSE.txt). Important: **Python:** Requires Hello ImGui or ImmApp – standalone usage isn't supported due to internal threading requirements. ## Quick Start Python: ```python from imgui_bundle import imgui, hello_imgui my_test: imgui.test_engine.Test def my_register_tests(): global my_test engine = hello_imgui.get_imgui_test_engine() my_test = imgui.test_engine.register_test(engine, "My Tests", "Click Button") def test_func(ctx: imgui.test_engine.TestContext): ctx.item_click("**/My Button") my_test.test_func = test_func def gui(): test_engine = hello_imgui.get_imgui_test_engine() if imgui.button("My Button"): print("Clicked!") if imgui.button("Run Tests"): imgui.test_engine.queue_test(test_engine, my_test) params = hello_imgui.RunnerParams() params.use_imgui_test_engine = True params.callbacks.register_tests = my_register_tests params.callbacks.show_gui = gui hello_imgui.run(params) ``` C++: ```cpp #include "hello_imgui/hello_imgui.h" #include "imgui_test_engine/imgui_te_engine.h" #include "imgui_test_engine/imgui_te_context.h" ImGuiTest * myTest = nullptr; void RegisterTests() { ImGuiTestEngine* engine = HelloImGui::GetImGuiTestEngine(); myTest = ImGuiTestEngine_RegisterTest(engine, "My Tests", "Click Button"); myTest->TestFunc = [](ImGuiTestContext* ctx) { ctx->ItemClick("**/My Button"); }; } void Gui() { auto testEngine = HelloImGui::GetImGuiTestEngine(); if (ImGui::Button("My Button")) printf("Clicked!\n"); if (ImGui::Button("Run Tests")) ImGuiTestEngine_QueueTest(testEngine, myTest); } int main() { HelloImGui::RunnerParams params; params.useImGuiTestEngine = true; params.callbacks.RegisterTests = RegisterTests; params.callbacks.ShowGui = Gui; HelloImGui::Run(params); return 0; } ``` ## Full demo For more complete examples, see the test engine demo from the interactive explorer: * [Try online](https://imgui-bundle.pages.dev/explorer/demo_testengine.html) * [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_testengine.py) * [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_testengine.cpp) ## Named References Test Engine uses "named references" to find widgets. The syntax uses path separators: | Pattern | Meaning | |---------|---------| | `"Button"` | Widget named "Button" in current reference | | `"**/Button"` | Search for "Button" anywhere in children | | `"//Window/Button"` | Absolute path from root | | `"$FOCUSED"` | Currently focused window | ```python ctx.set_ref("My Window") # Set current reference ctx.item_click("**/Save") # Find "Save" anywhere in window ctx.item_click("//Dialog/OK") # Absolute path to OK button ``` ## Common Actions ```python # Click items ctx.item_click("**/Button") ctx.item_double_click("**/Item") # Input text ctx.item_input("**/Name", "John Doe") # Check/uncheck ctx.item_check("**/Enable") ctx.item_uncheck("**/Disable") # Open/close tree nodes ctx.item_open("**/Settings") ctx.item_close("**/Settings") ctx.item_open_all("**/Tree") # Screenshots ctx.capture_screenshot_window("Window Name") # Keyboard input ctx.key_press(imgui.Key.enter) ctx.key_chars("Hello") ``` ## Assertions Use the `CHECK` function to verify conditions: ```python from imgui_bundle.imgui.test_engine_checks import CHECK def test_func(ctx: imgui.test_engine.TestContext): ctx.item_click("**/Increment") CHECK(counter == 1) # Verify counter was incremented ``` ## Custom Test GUI Tests can display their own GUI: ```python my_test = imgui.test_engine.register_test(engine, "Category", "Test Name") def test_gui_func(ctx: imgui.test_engine.TestContext): imgui.text("Custom test controls here") if imgui.button("Do Something"): # Custom action pass my_test.gui_func = test_gui_func ``` ## Driving a GUI and capturing screenshots — `immapp.testing` ImGui Bundle ships a small testing module that combines the test engine with screenshot capture. Use it when you want to script an interaction (click, type, expand a header) and grab a PNG at chosen moments: automated tests, documentation pictures. It is also how an AI agent sees and drives the app it writes, with nobody at the mouse: the bundle's screenshot skills (`.claude/skills/`) are built on it. - `immapp.testing.run(gui, test_fn, ...)` — Python: runs the GUI and drives it with `test_fn(ctx)`; exits once the test finishes (override with `exit_after_test=False`). An app with its own params: `run(test_function=test_fn, runner_params=params, add_ons_params=add_ons)`. - `immapp.testing.capture(ctx, path, window=None, flags=0)` — Python: write a PNG from inside a test. Captures the full framebuffer, or a single window if `window="My Window"`. - `immapp.testing.capture_final_frame(gui, path, ...)` — Python one-shot: run the GUI for a few frames, save the final frame. No test engine. - `ImmApp::Testing::Capture(ctx, path, {window, flags})` — C++ equivalent of `capture`, from `immapp/testing.h`. - `ImmApp::Testing::CaptureFinalFrame(guiFn, path, opts)` — C++ one-shot. Example: ```python from imgui_bundle import imgui from imgui_bundle.immapp import testing def gui(): imgui.button("Click me") def my_test(ctx: imgui.test_engine.TestContext): testing.capture(ctx, "/tmp/00_initial.png") ctx.item_click("//**/Click me") testing.capture(ctx, "/tmp/01_after_click.png") testing.run(gui, my_test, window_size=(600, 400)) ``` See the full demo in [`demo_immapp_testing.py`](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_immapp_testing.py) and [`demo_immapp_testing.cpp`](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_immapp_testing.cpp). ## Running Tests When test engine is enabled: 1. A "Test Engine" window appears 2. Click tests to run them 3. Watch as actions are automated 4. Check results (green = pass, red = fail) ## In the browser (Pyodide) The test engine works in the browser since v1.93, with the same API. Its coroutine, a thread on the desktop, is a WebAssembly stack switch there (JSPI), which needs Chrome 137, Firefox 153 or Safari 27. In an older browser, the app runs without the engine: `use_imgui_test_engine` is turned off, `get_imgui_test_engine()` returns `None`, and a message says so on stderr. `immapp.testing.run()` cannot block in the browser: it returns at once, the test runs in the frames that follow, the app stays open after it, and the result is printed when the test ends (stderr on failure). The screenshots go to Pyodide's virtual file system, and a "Captures" window shows them when the test ends: click one to enlarge it, or download it. While the engine runs, Python's automatic garbage collection is replaced by explicit collections at each frame (a workaround for a Pyodide bug with suspended stacks, pyodide#6464): a test that calls `gc.enable()` reopens it. ## Documentation & Resources - **[Test Engine Wiki](https://github.com/ocornut/imgui_test_engine/wiki)** - Official documentation - **[Named References](https://github.com/ocornut/imgui_test_engine/wiki/Named-References)** - Path syntax reference -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/addons/plotting/ # Plotting Libraries Dear ImGui Bundle includes two powerful plotting libraries for 2D and 3D visualization. ## ImPlot - 2D Plotting ### Introduction [ImPlot](https://github.com/epezent/implot) adds interactive 2D plots to your GUI: line charts, bar charts, scatter plots, heatmaps, and more. Plots support zooming, panning, and hover inspection. Link: https://github.com/epezent/implot Some of the many plot types supported by ImPlot. **Quick example:** Python: ```python from imgui_bundle import implot, immapp import numpy as np x = np.arange(0, 10, 0.1) y = np.sin(x) def gui(): if implot.begin_plot("My Plot"): implot.plot_line("sin(x)", x, y) implot.end_plot() immapp.run(gui, with_implot=True) ``` Tip: Enable ImPlot by passing `with_implot=True` to `immapp.run()`. C++: ```cpp #include "immapp/immapp.h" #include "implot/implot.h" #include #include std::vector x, y; void gui() { if (ImPlot::BeginPlot("My Plot")) { ImPlot::PlotLine("sin(x)", x.data(), y.data(), x.size()); ImPlot::EndPlot(); } } int main() { for (double i = 0; i < 10; i += 0.1) { x.push_back(i); y.push_back(std::sin(i)); } HelloImGui::RunnerParams runner_params; runner_params.callbacks.ShowGui = gui; ImmApp::AddOnsParams addons; addons.withImplot = true; ImmApp::Run(runner_params, addons); return 0; } ``` Tip: In C++, enable ImPlot by setting `withImplot = true` in `ImmApp::AddOnsParams`. Note: **Plotting numpy arrays: arrays must share a dtype.** ImPlot's plot functions are templated on a single numeric type, so every numpy array passed to one plot call must have the same dtype. Mixing, for example, an integer array with a float array raises an error: ```python xs = np.arange(100) # int64 ys = np.random.rand(100) # float64 # WRONG: int64 xs vs float64 ys -> raises a clear error implot.plot_scatter("s", xs, ys) # RIGHT: convert to a common dtype first implot.plot_scatter("s", xs.astype(ys.dtype), ys) ``` Mismatched dtypes raise an explicit error (naming both dtypes and the fix) instead of silently plotting garbage. The constraint is per call: you may use different dtypes across different plot calls. It applies to every multi-array function in `implot` and `implot3d`. See [issue #467](https://github.com/pthom/imgui_bundle/issues/467). ### Python: context managers (implot_ctx) In Python, `implot_ctx` provides context managers that pair each `implot.begin_*()` / `push_*()` call with its matching `end_*()` / `pop_*()`: ```python from imgui_bundle import implot, implot_ctx, immapp import numpy as np x = np.arange(0, 10, 0.1) y = np.sin(x) def gui(): with implot_ctx.begin_plot("My Plot") as plot: if plot: # the plot may be collapsed or clipped: always test it implot.plot_line("sin(x)", x, y) immapp.run(gui, with_implot=True) ``` `implot_ctx.begin_plot` and `begin_subplots` return an object that must be truth-tested before drawing. The `push_*` context managers (`push_style_color`, `push_style_var`, `push_colormap`, `push_plot_clip_rect`) need no test: they simply pop automatically. Note: `imgui_ctx` offers the same facility for the `imgui.begin_*()` functions. Both are demonstrated in the explorer's demos (Python specifics): *demo_python_context_manager*. ### Full Demo Link: https://pthom.github.io/imgui_explorer/?lib=implot ImPlot demo showcasing various plot types and features. - [Try online](https://pthom.github.io/imgui_explorer/?lib=implot): the explorer shows each demo running side by side with its code (Python or C++), so it can be used as a reference when writing your own plots. - Python demo code: [implot_demo.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_imgui_explorer/implot_demo.py) - C++ demo code: [implot_demo.cpp](https://github.com/epezent/implot/blob/master/implot_demo.cpp) ### Documented APIs - Python API reference: [implot/\_\_init\_\_.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/implot/__init__.pyi) - C++ API reference: [implot.h](https://github.com/epezent/implot/blob/master/implot.h) ## ImPlot3D - 3D Plotting ### Introduction [ImPlot3D](https://github.com/brenocq/implot3d) extends ImPlot with 3D visualization capabilities. Create interactive 3D line plots, scatter plots, surface plots, and more with rotation, zoom, and pan controls. Link: https://github.com/brenocq/implot3d Some of the plot types supported by ImPlot3D. **Quick example:** Python: ```python from imgui_bundle import implot3d, immapp, hello_imgui import numpy as np t = np.linspace(0, 10, 100) x, y, z = np.cos(t), np.sin(t), t def gui(): if implot3d.begin_plot("3D Helix", hello_imgui.em_to_vec2(30, 30)): implot3d.setup_axes("X", "Y", "Z") implot3d.plot_line("helix", x, y, z) implot3d.end_plot() immapp.run(gui, with_implot3d=True) ``` Tip: Enable ImPlot3D by passing `with_implot3d=True` to `immapp.run()`. C++: ```cpp #include "immapp/immapp.h" #include "implot3d/implot3d.h" #include #include std::vector x, y, z; void gui() { if (ImPlot3D::BeginPlot("3D Helix")) { ImPlot3D::SetupAxes("X", "Y", "Z"); ImPlot3D::PlotLine("helix", x.data(), y.data(), z.data(), x.size()); ImPlot3D::EndPlot(); } } int main() { for (double t = 0; t < 10; t += 0.1) { x.push_back(std::cos(t)); y.push_back(std::sin(t)); z.push_back(t); } HelloImGui::RunnerParams runner_params; runner_params.callbacks.ShowGui = gui; ImmApp::AddOnsParams addons; addons.withImplot3d = true; ImmApp::Run(runner_params, addons); return 0; } ``` Tip: In C++, enable ImPlot3D by setting `withImplot3d = true` in `ImmApp::AddOnsParams`. ### Full Demo The full demo for ImPlot3D is available online. [Try online](https://pthom.github.io/imgui_explorer/?lib=implot3d) - Python demo code: [implot3d_demo.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_imgui_explorer/implot3d_demo.py) - C++ demo code: [implot3d_demo.cpp](https://github.com/brenocq/implot3d/blob/main/implot3d_demo.cpp) ### Documented APIs - Python API reference: [implot3d/\_\_init\_\_.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/implot3d/__init__.pyi) - C++ API reference: [implot3d.h](https://github.com/brenocq/implot3d/blob/main/implot3d.h) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/addons/visualization/ # Image Visualization Dear ImGui Bundle includes specialized tools for image inspection and debugging. ## ImmVision - Image Viewer Widget ### Introduction [ImmVision](https://github.com/pthom/immvision) provides an interactive image viewer widget for ImGui applications, with zoom, pan, pixel inspection, and colormap support. Useful for building image processing tools and debugging computer vision pipelines from within your application. Link: https://github.com/pthom/immvision ImmVision: interactive image display with zoom, pan, and pixel inspection. **Quick example:** Python: ```python from imgui_bundle import immvision, immapp import numpy as np image = np.zeros((100, 100, 3), dtype=np.uint8) params = immvision.ImageParams() def gui(): # Simple display immvision.image_display("Simple", image) # Full interactivity (zoom, pan, pixel inspection) immvision.image("Interactive", image, params) immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "immvision/immvision.h" #include cv::Mat image; ImmVision::ImageParams params; void gui() { // Simple display ImmVision::ImageDisplay("Simple", image); // Full interactivity ImmVision::Image("Interactive", image, ¶ms); } int main() { ImmVision::UseBgrColorOrder(); image = cv::Mat::zeros(100, 100, CV_8UC3); ImmApp::Run(gui); return 0; } ``` Note: This example uses `cv::Mat` from OpenCV, but **OpenCV is optional**. ImmVision works standalone with its own `ImmVision::ImageBuffer` type. If you don't need OpenCV, replace `cv::Mat` with `ImageBuffer` and remove `UseBgrColorOrder()` (RGB is the default). To pass `cv::Mat` to ImmVision, your application must define `IMMVISION_HAS_OPENCV` and link OpenCV by itself (ImmVision never links it, the conversions are header-only): ```cmake find_package(OpenCV REQUIRED) target_compile_definitions(my_app PRIVATE IMMVISION_HAS_OPENCV) target_link_libraries(my_app PRIVATE opencv_core) ``` **Features:** - Zoom in/out using the mouse wheel - Pixel values displayed at high zoom levels - Pan by dragging with left mouse button - Settings panel for colormap, channels, etc. Tip: Images are in RGB order by default. For OpenCV (BGR) images, call `immvision.use_bgr_color_order()` once at startup. ### Full Demo Link: https://imgui-bundle.pages.dev/explorer/demo_immvision_launcher.html Click the image to run a launcher that includes several examples. | Demo | Python | C++ | |------|--------|-----| | Display Image | [demo_immvision_display.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immvision/demo_immvision_display.py) | [demo_immvision_display.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immvision/demo_immvision_display.cpp) | | Link Images Zoom/Pan | [demo_immvision_link.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immvision/demo_immvision_link.py) | [demo_immvision_link.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immvision/demo_immvision_link.cpp) | | Image Inspector | [demo_immvision_inspector.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immvision/demo_immvision_inspector.py) | [demo_immvision_inspector.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immvision/demo_immvision_inspector.cpp) | | Image Processing | [demo_immvision_process.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immvision/demo_immvision_process.py) | [demo_immvision_process.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immvision/demo_immvision_process.cpp) | ### Documented APIs - **Python:** [immvision.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/immvision.pyi) - **C++:** [image.h](https://github.com/pthom/immvision/blob/master/src/immvision/image.h) | [inspector.h](https://github.com/pthom/immvision/blob/master/src/immvision/inspector.h) ## ImmDebug — Standalone Image Debugger [Video tutorial on Youtube](https://www.youtube.com/watch?v=ztVBk2FN6_8) ImmDebug a tool from [ImmVision](https://github.com/pthom/immvision) lets you visually inspect images from any running program — during execution or even after it finishes (post-mortem). Add one-line calls to send images to a standalone viewer with zoom, pan, pixel inspection, and colormaps. The immdebug viewer displaying images sent from a running program. ### Python Install from PyPI: ```bash pip install immdebug ``` Start the viewer in a terminal, then send images from your code: ```python # In a terminal: immdebug-viewer import numpy as np import cv2 from immdebug import immdebug image = cv2.imread("photo.jpg") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 100, 200) immdebug(image, "image") # inspect the original image immdebug(gray, "gray") # inspect different steps of your processing pipeline immdebug(edges, "edges") ``` Works with OpenCV, PIL, matplotlib, or any numpy array. See the [immdebug PyPI package](https://pypi.org/project/immdebug/) for full API documentation. ### C++ Drop 4 files from [src/immdebug](https://github.com/pthom/immvision/tree/master/src/immdebug) into your project (only OpenCV required): ```cpp #include "immdebug/immdebug.h" cv::Mat image = cv::imread("photo.jpg"); ImmVision::ImmDebug(image, "original"); ``` Build and run the C++ viewer separately — see the [immvision README](https://github.com/pthom/immvision) for instructions. ### Features - **Non-blocking** — just writes a file and returns immediately - **Cross-language** — C++ and Python clients use the same protocol, both work with either viewer - **Post-mortem** — images persist in the temp directory for 1 hour; start the viewer after your script finishes - **Single instance** — re-launching the viewer brings the existing instance to the top ## imgui_tex_inspect - Texture Inspector ### Introduction [imgui_tex_inspect](https://github.com/andyborrell/imgui_tex_inspect) is a texture inspector tool for debugging GPU textures. It displays textures with zoom, pan, and detailed pixel information. Link: https://github.com/andyborrell/imgui_tex_inspect imgui_tex_inspect: GPU texture inspection with zoom and pixel details. Tip: Enable imgui_tex_inspect by passing `with_tex_inspect=True` (Python) or `addons.withTexInspect = true` (C++). ### Full Demo - [Demo Window](https://imgui-bundle.pages.dev/explorer/demo_tex_inspect_demo_window.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_tex_inspect/demo_tex_inspect_demo_window.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_tex_inspect/demo_tex_inspect_demo_window.cpp) - [Simple Example](https://imgui-bundle.pages.dev/explorer/demo_tex_inspect_simple.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_tex_inspect/demo_tex_inspect_simple.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_tex_inspect/demo_tex_inspect_simple.cpp) ### Documented APIs - **Python:** [imgui_tex_inspect.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_tex_inspect.pyi) - **C++:** [imgui_tex_inspect.h](https://github.com/pthom/imgui_tex_inspect/blob/main/imgui_tex_inspect.h) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/addons/text-markdown/ # Text Editing & Markdown Dear ImGui Bundle includes libraries for syntax-highlighted text editing and markdown rendering. ## rich_md - Markdown Rendering ### Introduction [imgui_rich_md](https://github.com/pthom/imgui_rich_md) renders markdown content directly in your ImGui interface: headers, emphasis, links, lists, tables, images, code blocks with syntax highlighting, LaTeX math, admonitions and collapsible sections. Its text can be selected with the mouse and copied (Ctrl+C, Cmd+C on macOS); a right click also copies it as markdown. It is a standalone library that also works on stock Dear ImGui (C++); Dear ImGui Bundle includes it, with Python bindings. In Python the module is `imgui_bundle.rich_md`; in C++ the namespace is `RichMd`. The former names, `imgui_md` (Python) and `ImGuiMd` (C++), remain available as aliases. **Quick example:** Python: ```python from imgui_bundle import rich_md, immapp def gui(): rich_md.render(""" # Hello Markdown This is **bold** and this is *italic*. - List item 1 - List item 2 """) immapp.run(gui, with_markdown=True) ``` `rich_md.render(s)` removes the common indentation of the string first, so that a string written inside an indented function renders as expected. `rich_md.render_raw(s)` renders it as is. C++: ```cpp #include "immapp/immapp.h" #include "imgui_rich_md/rich_md.h" void gui() { RichMd::Render(R"( # Hello Markdown This is **bold** and this is *italic*. - List item 1 - List item 2 )"); } int main() { ImmApp::RunWithMarkdown(gui); return 0; } ``` Tip: Enable markdown by passing `with_markdown=True` to `immapp.run()` (Python) or use `ImmApp::RunWithMarkdown()` (C++). ### Images rich_md supports images from local assets and from URLs. **Standard markdown images:** ```markdown ![local image](images/world.png) ![online image](https://example.com/photo.jpg) ``` **HTML img tags with explicit size:** ```html ``` Note: **Python:** URL images are downloaded asynchronously (a loading spinner is shown while downloading). This works automatically when using `immapp.run(with_markdown=True)`. The download function can be replaced with `rich_md.set_download_function(fn)`. **C++ (Emscripten):** URL images are downloaded automatically using `emscripten_fetch` (non-blocking, async). **C++ (desktop):** URL images are not downloaded by default. To enable them, build with `IMGUI_RICHMD_WITH_DOWNLOAD_IMAGES` (libcurl), or set `HostServices::Download` (see `rich_md_host.h`) to a function that downloads data from a URL and returns a `MarkdownDownloadResult` with `Ready`/`Downloading`/`Failed` status. ### LaTeX math rich_md renders inline and display LaTeX math with [MicroTeX](https://github.com/NanoMichael/MicroTeX) (the bundle uses [a fork](https://github.com/pthom/MicroTeX)). **Quick example:** Python: ```python from imgui_bundle import rich_md, immapp def gui(): rich_md.render(r""" # Math in markdown Inline math sits on the text baseline: $E = mc^2$, $\sqrt{a^2 + b^2}$, $\sum_{i=0}^{n} i = \frac{n(n+1)}{2}$. Display math is centered on its own line: $$ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$ Sums, integrals, matrices all work: $$ \int_{-\infty}^{\infty} e^{-x^2}\, dx = \sqrt{\pi} \qquad A = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \qquad e^{i\pi} + 1 = 0 $$ """) immapp.run(gui, with_latex=True) # implies with_markdown=True ``` Note the **raw string** (`r"""..."""`): without it, Python would interpret sequences like `\theta` as escape characters and silently corrupt the LaTeX. C++: ```cpp #include "immapp/immapp.h" #include "imgui_rich_md/rich_md.h" void gui() { RichMd::Render(R"( # Math in markdown Inline math: $E = mc^2$, $\sqrt{a^2 + b^2}$. $$ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$ )"); } int main() { ImmApp::AddOnsParams addons; addons.withLatex = true; // implies withMarkdown=true HelloImGui::SimpleRunnerParams simple; simple.guiFunction = gui; ImmApp::Run(simple, addons); return 0; } ``` Tip: Enable LaTeX math by passing `with_latex=True` to `immapp.run()` (Python) or setting `addOnsParams.withLatex = true` (C++). Both imply markdown support: you do not need to also set `with_markdown=True`. - When LaTeX is **disabled** (the default), `$` is displayed as a normal character. - When LaTeX is **enabled**, `$` is treated as math delimiters. To include a literal `$`, escape it like this: `\$`. Note: Pyodide note Pyodide wheels do not include the math fonts required for rendering LaTeX (to save space, since they occupy about 500KB). They will be downloaded when needed: the download is triggered by a call to `immapp.run(with_latex=True)`. ### Mermaid diagrams ` ```mermaid ` blocks are drawn natively, with `ImDrawList` and the colors of the ImGui style: flowcharts, sequence diagrams and class diagrams (a subset of Mermaid). A diagram that cannot be parsed is shown as code, with the line of the error. ````markdown ```mermaid flowchart LR A[Markdown] --> B{Mermaid block?} B -->|yes| C([Parse]) --> D[Layout] B -->|no| E[Code block] ``` ```` To draw a diagram outside of markdown: `rich_md.render_mermaid(source)` (Python), `RichMd::RenderMermaid(source)` (C++). The library's [Mermaid tour](https://pthom.github.io/imgui_rich_md/mermaid.html) shows more of them, and [what is supported](https://github.com/pthom/imgui_rich_md/blob/main/docs/mermaid.md) lists the syntax it reads and how its layout differs from mermaid.js. ### Documents A long text reads better as a document: a scroll area of its own, a table of contents beside it, links between its sections, and a search. Python: ```python from imgui_bundle import imgui, immapp, rich_md def gui() -> None: with rich_md.document("doc"): rich_md.render("# Intro\n\nSee [the widgets](#a-section-of-widgets).\n\n## Details\n\nSome text.") rich_md.document_heading(2, "A section of widgets") imgui.button("A button") rich_md.render("## The end\n\nBack to [the top](#intro).") immapp.run(gui, with_markdown=True) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui_rich_md/rich_md.h" void Gui() { RichMd::BeginDocument("doc"); RichMd::Render("# Intro\n\nSee [the widgets](#a-section-of-widgets).\n\n## Details\n\nSome text."); RichMd::DocumentHeading(2, "A section of widgets"); ImGui::Button("A button"); RichMd::Render("## The end\n\nBack to [the top](#intro)."); RichMd::EndDocument(); } int main() { ImmApp::AddOnsParams addons; addons.withMarkdown = true; HelloImGui::SimpleRunnerParams simple; simple.guiFunction = Gui; ImmApp::Run(simple, addons); return 0; } ``` - Between the start and the end of a document, call `render()` as many times as you like, and any other widget: they share one table of contents and one search. - `document_heading()` gives a section made of widgets its heading. - A link `[text](#slug)` reaches a heading of any render of the document. The slugs are made as GitHub does: `## Headings and anchors` is `#headings-and-anchors`, and a repeated title gets `-1`, `-2`. - The search opens with Ctrl+F (Cmd+F on macOS), or with the magnifier of a narrow document. Enter goes to the next match, Shift+Enter to the previous one. The matches are also listed under the find bar and in the Search tab, and marked on the scrollbar. - The search also finds the text of the collapsed sections (a jump opens them), of the code blocks, and of the formulas (their LaTeX source). - Headings that fold: with `foldable_headings` in `DocumentOptions` (or in the context's `MarkdownOptions`), an arrow at the left of each heading, from `##` on, folds its section until the next heading of the same level or above, across the renders. `document_heading()` returns False when its section is folded: skip its widgets then. The right-click menu and the "..." menu of the table of contents fold or unfold them all, as `fold_all_headings()` does. - `render_document(id, markdown)` is the one-call form, and `DocumentOptions` sets the table of contents, the search, the scroll's animation and the folds. Demo: [Try online](https://imgui-bundle.pages.dev/explorer/demo_imgui_md_document.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demo_imgui_md_document.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demo_imgui_md_document.cpp) ### Narrative programming A program can tell its own story. Its comments and strings hold named markdown sections (`::md Name`) and code regions (`::code`), and markdown transcludes them with an embed alone on its line, as in Obsidian: `![[#Square]]` for the prose of a section, `![[#Square#code]]` for its code, `![[other_file.py#Name]]` for another file. The story chooses its order; the program keeps its own. Python: ```python from imgui_bundle import immapp, rich_md r"""::md Intro # A program that tells its own story The story picks the parts of the file it needs, in its own order: ![[#Square]] ![[#Square#code]] """ # ::md Square # The square of a number, $x^2$: # ::code def square(x: float) -> float: return x * x # ::endcode def gui() -> None: rich_md.render_this_file("Intro") immapp.run(gui, with_latex=True) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui_rich_md/rich_md.h" /*::md Intro # A program that tells its own story The story picks the parts of the file it needs, in its own order: ![[#Square]] ![[#Square#code]] */ // ::md Square // The square of a number, $x^2$: // ::code float Square(float x) { return x * x; } // ::endcode void Gui() { RICHMD_RENDER_THIS_FILE("Intro"); } int main() { ImmApp::AddOnsParams addons; addons.withLatex = true; HelloImGui::SimpleRunnerParams simple; simple.guiFunction = Gui; ImmApp::Run(simple, addons); return 0; } ``` `RICHMD_RENDER_THIS_FILE` reads the source file (`__FILE__`) at run time: the source must be present where the program runs. `render_this_file("Intro")` renders the section `Intro` of the calling file, its transclusions resolved. A section written in line comments ends with its code (`::endcode`), or with `::endmd` when it has none; a section in a string or a block comment ends with it. Example: [the Mandelbrot set as a map of Julia sets](https://imgui-bundle.pages.dev/playground/?demo=explorables/julia_map/julia_map.py), an interactive lesson in a single Python file ([source](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/playground/examples/explorables/julia_map/julia_map.py)). The idea: [narrative programming](https://github.com/pthom/imgui_rich_md/blob/main/docs/narrative_programming/narrative_programming.md); the syntax in full: [specification](https://github.com/pthom/imgui_rich_md/blob/main/docs/narrative_programming/narrative_programming_spec.md). ### Full Demo [Try online](https://imgui-bundle.pages.dev/explorer/demo_imgui_md.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demo_imgui_md.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demo_imgui_md.cpp) The library's own examples, on stock Dear ImGui (C++): a tour of every feature, an editor, a custom host, fonts. [Try online](https://pthom.github.io/imgui_rich_md/) | [C++](https://github.com/pthom/imgui_rich_md/tree/main/examples) ### Documented APIs - **Python:** [rich_md.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/rich_md.pyi) - **C++:** [rich_md.h](https://github.com/pthom/imgui_rich_md/blob/main/imgui_rich_md/rich_md.h) (and [rich_md_host.h](https://github.com/pthom/imgui_rich_md/blob/main/imgui_rich_md/rich_md_host.h) to plug your own textures, assets or downloads) ## ImGuiColorTextEdit - Syntax Highlighting Editor & Diff Viewer ### Introduction [ImGuiColorTextEdit](https://github.com/goossens/ImGuiColorTextEdit) is a syntax highlighting text editor and diff viewer for ImGui (originally by BalazsJako, rewritten from scratch by Johan A. Goossens). Dear ImGui Bundle uses a [fork](https://github.com/pthom/ImGuiColorTextEdit/tree/imgui_bundle) with a few additions for Python bindings. **Features:** - Syntax highlighting for C, C++, Python, GLSL, HLSL, Lua, SQL, AngelScript, C#, JSON, Markdown - Multiple color palettes (dark, light) - Find/replace UI with keyboard shortcuts - Text markers (colored line highlights with tooltips) - Bracket matching with visual indicators - Line decorators (custom gutter content per line, e.g. breakpoints) - Context menu callbacks (separate for line numbers and text area) - Change and transaction callbacks - Filter selections/lines (transform text via callbacks) - Autocomplete framework - Undo/redo, copy/paste, multi-cursor support - **TextDiff widget**: combined and side-by-side diff view for comparing two texts Tip: The text editor requires a fixed-width font. If you are using ImmApp with Markdown enabled, you may use its code font: ```python code_font = rich_md.get_code_font() imgui.push_font(code_font.font, code_font.size) editor.render("Code") imgui.pop_font() ``` ### Full Demo [Try online](https://imgui-bundle.pages.dev/explorer/demo_text_edit.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demo_text_edit.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demo_text_edit.cpp) ### Documented APIs - **Python:** [imgui_color_text_edit.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_color_text_edit.pyi) - **C++:** [TextEditor.h](https://github.com/pthom/ImGuiColorTextEdit/blob/imgui_bundle/TextEditor.h) | [TextDiff.h](https://github.com/pthom/ImGuiColorTextEdit/blob/imgui_bundle/TextDiff.h) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/addons/tools/ # Tools Dear ImGui Bundle includes specialized tools for 3D editing and visual programming. ## ImGuizmo - 3D Gizmos ### Introduction [ImGuizmo](https://github.com/CedricGuillemet/ImGuizmo) provides immediate mode 3D gizmos for scene editing: translate, rotate, and scale manipulators similar to those found in 3D modeling software. Link: https://github.com/CedricGuillemet/ImGuizmo ImGuizmo: 3D gizmos for translation, rotation, and scale. **Features:** - Translation, rotation, scale gizmos - Local and world coordinate modes - View cube for camera orientation - Snap to grid support ### Full Demo [Try online](https://imgui-bundle.pages.dev/explorer/demo_gizmo.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_imguizmo/demo_gizmo.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_imguizmo/demo_gizmo.cpp) ### Documented APIs - **Python:** [imguizmo.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imguizmo.pyi) - **C++:** [ImGuizmo.h](https://github.com/CedricGuillemet/ImGuizmo/blob/master/ImGuizmo.h) ## imgui-node-editor - Visual Node Graphs ### Introduction [imgui-node-editor](https://github.com/thedmd/imgui-node-editor) is a node editor built using Dear ImGui. Create visual programming interfaces, data flow graphs, etc. Link: https://github.com/thedmd/imgui-node-editor imgui-node-editor: visual node graphs for data flow and shader editing. Link: https://pthom.github.io/fiatlight Note: [Fiatlight](https://pthom.github.io/fiatlight), a library built on top of Dear ImGui Bundle uses imgui-node-editor intensively. It provides an automatic UI generation for functions and structured data. Tip: Enable the node editor by passing `with_node_editor=True` (Python) or `addons.withNodeEditor = true` (C++). ### Demos Each demo opens in the online playground from its name. | Demo | Python | C++ | |------|--------|-----| | [A color mixer](https://imgui-bundle.pages.dev/playground/?demo=demo_node_editor_color_mixer.py): colors flow through a graph | [demo_node_editor_color_mixer.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_node_editor/demo_node_editor_color_mixer.py) | [demo_node_editor_color_mixer.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_node_editor/demo_node_editor_color_mixer.cpp) | | [An image pipeline](https://imgui-bundle.pages.dev/playground/?demo=demo_node_editor_image_pipeline.py): filters, typed pins, a histogram in a node | [demo_node_editor_image_pipeline.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_node_editor/demo_node_editor_image_pipeline.py) | [demo_node_editor_image_pipeline.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_node_editor/demo_node_editor_image_pipeline.cpp) | ### Documented APIs - **Python:** [imgui_node_editor.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_node_editor.pyi) - **C++:** [imgui_node_editor.h](https://github.com/pthom/imgui-node-editor/blob/imgui_bundle/imgui_node_editor.h) ## NanoVG - 2D Vector Graphics ### Introduction [NanoVG](https://github.com/memononen/nanovg) is an antialiased 2D vector drawing library on top of OpenGL. Use it for custom drawing, charts, diagrams, or any vector graphics needs. Link: https://github.com/memononen/nanovg NanoVG: antialiased 2D vector graphics with paths, shapes, and text. **Features:** - Antialiased rendering - Paths, shapes, gradients - Text rendering with font support - Scissoring and clipping ### Full Demo [Try online](https://imgui-bundle.pages.dev/explorer/demo_nanovg_launcher.html) - A launcher with two demos: | Demo | Python | C++ | |-------------|--------|-----| | Full Demo | [demo_nanovg_full.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_nanovg/demo_nanovg_full.py) | [demo_nanovg_full.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_nanovg/demo_nanovg_full.cpp) | | Simple Demo | [demo_nanovg_heart.py](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_nanovg/demo_nanovg_heart.py) | [demo_nanovg_heart.cpp](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_nanovg/demo_nanovg_heart.cpp) | ### Documented APIs - **Python:** [nanovg.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/nanovg.pyi) - **C++:** [nanovg.h](https://github.com/memononen/nanovg/blob/master/src/nanovg.h) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/addons/widgets/ # Widgets Dear ImGui Bundle includes a variety of additional widgets beyond the standard ImGui set. ## Full Demo Link: https://imgui-bundle.pages.dev/explorer/demo_widgets.html Widgets demo showcasing knobs, toggles, spinners, coolbar, and more. [Try online](https://imgui-bundle.pages.dev/explorer/demo_widgets.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demo_widgets.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demo_widgets.cpp) ## imgui-knobs - Rotary Knobs ### Introduction [imgui-knobs](https://github.com/altschuler/imgui-knobs) adds rotary knob widgets similar to those found in audio software. Link: https://github.com/altschuler/imgui-knobs imgui-knobs: rotary knobs with multiple visual styles. **Knob variants:** `tick`, `dot`, `wiper`, `wiper_only`, `stepped` ### Quick Example Python: ```python from imgui_bundle import imgui_knobs, immapp value = 50.0 def gui(): global value changed, value = imgui_knobs.knob("Volume", value, 0.0, 100.0) immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui-knobs/imgui-knobs.h" float value = 50.0f; void gui() { ImGuiKnobs::Knob("Volume", &value, 0.0f, 100.0f); } int main() { ImmApp::Run(gui, "Knobs Demo", {400, 300}); return 0; } ``` ### Documented APIs - **Python:** [imgui_knobs.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_knobs.pyi) - **C++:** [imgui-knobs.h](https://github.com/altschuler/imgui-knobs/blob/main/imgui-knobs.h) ## imgui_toggle - Toggle Switches ### Introduction [imgui_toggle](https://github.com/cmdwtf/imgui_toggle) provides iOS-style toggle switches. Link: https://github.com/cmdwtf/imgui_toggle imgui_toggle: iOS-style toggle switches with animations. ### Quick Example Python: ```python from imgui_bundle import imgui_toggle, immapp enabled = False def gui(): global enabled changed, enabled = imgui_toggle.toggle("Enable feature", enabled) immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "imgui_toggle/imgui_toggle.h" bool enabled = false; void gui() { ImGui::Toggle("Enable feature", &enabled); } int main() { ImmApp::Run(gui, "Toggle Demo", {400, 300}); return 0; } ``` ### Documented APIs - **Python:** [imgui_toggle.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_toggle.pyi) - **C++:** [imgui_toggle.h](https://github.com/cmdwtf/imgui_toggle/blob/main/imgui_toggle.h) ## imspinner - Loading Spinners ### Introduction [imspinner](https://github.com/dalerank/imspinner) provides a large collection of animated loading spinners. Tip: Call `imspinner.demo_spinners()` (Python) or `ImSpinner::demoSpinners()` (C++) to see all available spinner types. ### Quick Example Python: ```python from imgui_bundle import imspinner, imgui, immapp def gui(): imspinner.spinner_ang_triple( "spinner", radius1=16, radius2=13, radius3=10, thickness=3, c1=imgui.ImColor(255, 255, 255), c2=imgui.ImColor(255, 100, 100), c3=imgui.ImColor(100, 100, 255) ) immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "imspinner/imspinner.h" void gui() { ImSpinner::SpinnerAngTriple( "spinner", 16, 13, 10, // radii 3, // thickness ImColor(255, 255, 255), ImColor(255, 100, 100), ImColor(100, 100, 255) ); } int main() { ImmApp::Run(gui, "Spinner Demo", {400, 300}); return 0; } ``` ### Documented APIs - **Python:** [imspinner.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imspinner.pyi) - **C++:** [imspinner.h](https://github.com/dalerank/imspinner/blob/master/imspinner.h) ## ImCoolBar - macOS-style Dock Bar ### Introduction [ImCoolBar](https://github.com/aiekick/ImCoolBar) creates a macOS-style dock bar with magnification effect on hover. Link: https://github.com/aiekick/ImCoolBar ImCoolBar: macOS-style dock bar with magnification effect. ### Documented APIs - **Python:** [im_cool_bar.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/im_cool_bar.pyi) - **C++:** [ImCoolbar.h](https://github.com/aiekick/ImCoolBar/blob/master/ImCoolbar.h) ## imgui-command-palette - VSCode-style Command Palette ### Introduction [imgui-command-palette](https://github.com/hnOsmium0001/imgui-command-palette) adds a Sublime Text / VSCode style command palette. Link: https://github.com/hnOsmium0001/imgui-command-palette imgui-command-palette: VSCode-style command palette. ### Full Demo [Try online](https://imgui-bundle.pages.dev/explorer/demo_command_palette.html) | [Python](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/demos_immapp/demo_command_palette.py) | [C++](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/demos_immapp/demo_command_palette.cpp) ### Documented APIs - **Python:** [imgui_command_palette.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/imgui_command_palette.pyi) - **C++:** [imcmd_command_palette.h](https://github.com/hnOsmium0001/imgui-command-palette/blob/master/imcmd_command_palette.h) ## File Dialogs Dear ImGui Bundle provides two file dialog libraries. ### portable-file-dialogs [portable-file-dialogs](https://github.com/samhocevar/portable-file-dialogs) uses native OS dialogs for file selection, notifications, and messages. Link: https://github.com/samhocevar/portable-file-dialogs portable-file-dialogs: native OS dialogs on all platforms. Note: On **Emscripten/Web**, only message dialogs (with an OK button and icon) are supported since native file dialogs are unavailable. On **Windows, Linux, and macOS**, all features work fully. #### Quick Example Python: ```python from imgui_bundle import portable_file_dialogs as pfd # Open file dialog (native OS) selection = pfd.open_file("Select a file", ".", ["Image Files", "*.png *.jpg"]) # Message box pfd.message("Title", "Message content", pfd.choice.ok, pfd.icon.info) ``` C++: ```cpp #include "portable-file-dialogs/portable-file-dialogs.h" // Open file dialog (native OS) auto selection = pfd::open_file("Select a file", ".", {"Image Files", "*.png *.jpg"}).result(); // Message box pfd::message("Title", "Message content", pfd::choice::ok, pfd::icon::info); ``` #### Documented APIs - **Python:** [portable_file_dialogs.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/portable_file_dialogs.pyi) - **C++:** [portable-file-dialogs.h](https://github.com/samhocevar/portable-file-dialogs/blob/master/portable-file-dialogs.h) ### ImFileDialog [ImFileDialog](https://github.com/dfranx/ImFileDialog) is a file dialog library with a modern look. Link: https://github.com/dfranx/ImFileDialog ImFileDialog: modern file dialog with preview support. Warning: Consider using **portable-file-dialogs** instead, which provides native OS dialogs on each platform plus notifications and messages. **Known limitations of ImFileDialog:** - Not adapted for High DPI resolution under Windows - No support for multi-selection - Will not work under Python with a pure Python backend (requires `immapp.run()`) #### Quick Example Python: ```python from imgui_bundle import im_file_dialog as ifd, imgui, immapp def gui(): if imgui.button("Open File"): ifd.FileDialog.instance().open( "OpenFile", "Open a file", "Image files (*.png;*.jpg){.png,.jpg},.*" ) if ifd.FileDialog.instance().is_done("OpenFile"): if ifd.FileDialog.instance().has_result(): result = ifd.FileDialog.instance().get_result() print(f"Selected: {result}") ifd.FileDialog.instance().close() immapp.run(gui) ``` C++: ```cpp #include "immapp/immapp.h" #include "ImFileDialog/ImFileDialog.h" void gui() { if (ImGui::Button("Open File")) { ifd::FileDialog::Instance().Open( "OpenFile", "Open a file", "Image files (*.png;*.jpg){.png,.jpg},.*" ); } if (ifd::FileDialog::Instance().IsDone("OpenFile")) { if (ifd::FileDialog::Instance().HasResult()) { auto result = ifd::FileDialog::Instance().GetResult(); printf("Selected: %s\n", result.string().c_str()); } ifd::FileDialog::Instance().Close(); } } int main() { ImmApp::Run(gui, "File Dialog", {800, 600}); return 0; } ``` #### Documented APIs - **Python:** [im_file_dialog.pyi](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/im_file_dialog.pyi) - **C++:** [ImFileDialog.h](https://github.com/pthom/ImFileDialog/blob/imgui_bundle/ImFileDialog.h) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/support/support-project/ # Support the project Dear ImGui Bundle is a free and open-source project, and its development and maintenance require considerable efforts. If you find it valuable for your work – especially in a commercial enterprise or a research setting – please consider supporting its development by [making a donation](https://www.paypal.com/donate/?hosted_button_id=SHJ68RVDKURZA). Your contributions are greatly appreciated! For commercial users seeking tailored support or specific enhancements, please contact the author by email. ## Contribute Quality contributions are always welcome! If you’re interested in contributing to the project, whether through code, ideas, or feedback, please refer to the development documentation. ## License Dear ImGui Bundle is licensed under the [MIT License](https://github.com/pthom/imgui_bundle/blob/main/LICENSE) -------------------------------------------------------------------------------- Page: https://imgui-bundle.pages.dev/doc/support/closing-words/ # Closing words ## License The MIT License (MIT) Copyright (c) 2021-2026 Pascal Thomet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## About the author Dear ImGui Bundle is developed by Pascal Thomet. I am reachable on my [Github page](https://github.com/pthom). I sometimes [blog](http://code-ballads.net/). There is a [playlist](https://www.youtube.com/playlist?list=PLaJx_KrDECZPzttQ77Gv8DD7OAUwmtWUc) related to ImGui Bundle on YouTube. I have a past in computer vision, and a lot of experience in the trenches between development and research teams; and I found ImGui to be a nice way to reduce the delay between a research prototype and its use in production code. I also have an inclination for self documenting code, and the doc you are reading was a way to explore new ways to document projects. ## How is Dear ImGui Bundle developed The development of the initial version of Dear ImGui Bundle took about one year at full time. The bindings are auto-generated thanks to an advanced parser, so that they are easy to keep up to date. Please be tolerant if you find issues! Dear ImGui Bundle is developed for free, under a very permissive license, by one main author (and most of its API comes from external libraries). If you need consulting about this library or about the bindings generator in the context of a commercial project, please contact me by email. Contributions are welcome! ## Thanks Dear ImGui Bundle would not be possible without the work of the authors of "Dear ImGui", and especially [Omar Cornut](https://www.miracleworld.net/). It also includes a lot of other projects, and I’d like to thank their authors for their awesome work! A particular mention for Evan Pezent (author of ImPlot), Cédric Guillemet (author of ImGuizmo), Balázs Jákó (author of ImGuiColorTextEdit), and Michał Cichoń (author of imgui-node-editor), and Dmitry Mekhontsev (author of imgui-md), Andy Borrel (author of imgui-tex-inspect, another image debugging tool, which I discovered long after having developed immvision). Immvision was inspired by [The Image Debugger](https://billbaxter.com/projects/imdebug/), by Bill Baxter.