Menus and Dialogs¶
Menus¶
Menus are defined with MenuDef and passed to app.build(). They must be created before the window (a libui-ng requirement):
"""Menus — file, edit, and help menus with various item types."""
import libui
from libui.declarative import (
App,
Window,
VBox,
Label,
State,
MenuDef,
MenuItem,
CheckMenuItem,
MenuSeparator,
QuitItem,
PreferencesItem,
AboutItem,
)
async def main():
app = App()
dark_mode = State(False)
status = State("Use the menus above.")
menus = [
MenuDef(
"File",
MenuItem(
"Open...",
on_click=lambda: status.set(
f"Open: {app.open_file() or '(cancelled)'}"
),
),
MenuItem(
"Save As...",
on_click=lambda: status.set(
f"Save: {app.save_file() or '(cancelled)'}"
),
),
MenuSeparator(),
QuitItem(),
),
MenuDef(
"Edit",
CheckMenuItem(
"Dark Mode",
checked=dark_mode,
on_click=lambda: status.set(f"Dark mode: {dark_mode.value}"),
),
MenuSeparator(),
PreferencesItem(),
),
MenuDef(
"Help",
AboutItem(),
MenuItem(
"Documentation",
on_click=lambda: app.msg_box(
"Help", "Visit the project repository for documentation."
),
),
),
]
app.build(
menus=menus,
window=Window(
"Menus",
500,
250,
has_menubar=True,
child=VBox(
Label(text=status),
),
),
)
app.show()
await app.wait()
libui.run(main())
Menu item types¶
Type |
Description |
|---|---|
|
Regular clickable item |
|
Checkable item, optionally bound to |
|
Visual separator line |
|
Platform quit item (Cmd+Q / Alt+F4) |
|
Platform preferences item |
|
Platform about item |
Set has_menubar=True on the Window to display the menu bar.
Dialogs¶
App provides dialog methods for file selection and message boxes:
"""Dialogs — file dialogs and message boxes (sync and async)."""
import libui
from libui.declarative import App, Window, VBox, Label, Button, State
async def main():
app = App()
status = State("")
def do_open():
path = app.open_file()
status.set(f"Opened: {path}" if path else "Open cancelled.")
def do_folder():
path = app.open_folder()
status.set(f"Folder: {path}" if path else "Folder cancelled.")
async def do_save_async():
path = await app.save_file_async()
status.set(f"Save to: {path}" if path else "Save cancelled.")
app.build(
window=Window(
"Dialogs",
400,
300,
child=VBox(
Label(text=status),
Button("Open File", on_clicked=do_open),
Button("Open Folder", on_clicked=do_folder),
Button("Save File (async)", on_clicked=do_save_async),
Button(
"Message Box",
on_clicked=lambda: app.msg_box("Info", "This is a message box."),
),
Button(
"Error Box",
on_clicked=lambda: app.msg_box_error(
"Error", "Something went wrong!"
),
),
),
)
)
app.show()
await app.wait()
libui.run(main())
Sync vs async dialogs¶
Dialog methods come in two flavors:
Sync (from main thread callbacks) |
Async (from coroutines) |
|---|---|
|
|
|
|
|
|
|
|
|
|
Use sync methods inside on_clicked lambdas (which run on the main thread). Use async methods inside async def callbacks.
File dialog methods return a path string, or None if the user cancelled.