Showcase app (recommended): run python examples/showcase.py.
Application object responsible for window lifecycle, widget construction scope, and event loop startup.
Methods:
window(callable)register the root builder (used as a decorator via@app.window)add_window(callable, title="TrueGraphics", width=640, height=480) -> intregister an additional window builder (created whenrun()is called)run()build the widget tree and start the Win32 message loopset_title(str)set the initial window title (call beforerun())set_size(width, height)set the initial window size (call beforerun())set_theme("dark" | "light")set theme used for default widget stylesset_fullscreen(bool)request fullscreen at startupset_icon(path: str)set window icon (best with.ico)set_min_size(w, h)set min track sizeset_max_size(w, h)set max track sizeset_timeout(seconds, callback) -> intrun callback once after delayset_interval(seconds, callback) -> intrun callback repeatedlyclear_timer(id)cancel a timeout/intervalpost(callback)schedule a callback to run on the UI thread on the next framerun_async(task, on_done=None)run a background task and optionally scheduleon_doneback on the UI threadon_shortcut("Ctrl+S", callback)register a simple shortcut handlerenable_tray(icon_path, tooltip="TrueGraphics", on_click=None)enable a system tray icon (best with.ico)disable_tray()remove tray icon
Notes:
- The window is resizable by default; container layouts are re-applied on resize.
- The renderer redraws continuously (timer-driven) and is double-buffered to avoid flicker.
Base bound widget object.
Common methods:
set_id(str)set_text(str)set_size(width, height)set_position(x, y)set_background(color)set_text_color(color)set_border_color(color)set_border_radius(int)set_border_width(int)set_padding(int)set_margin(int)set_font(family: str)set_font_size(size: int)set_focusable(bool)on_hover(callback(bool))on_mouse_move(callback(x, y))on_key_down(callback(key_code))on_char(callback(codepoint))on_drop_files(callback(list[str]))animate(property, to, duration=0.3, easing="smoothstep")on_mouse_down(callback(x, y))on_mouse_up(callback(x, y))
Properties:
text: str(read-only)id: str(read-only)x: int(read-only)y: int(read-only)width: int(read-only)height: int(read-only)
Construct a button widget.
Signature:
Button(text: str, on_click: Optional[Callable] = None)Construct a label widget.
Signature:
Label(text: str = "")Basic text input widget (ASCII for now). Becomes focused when clicked.
Signature:
TextBox(text: str = "")Clickable checkbox with an on_change callback.
Signature:
Checkbox(text: str = "", checked: bool = False, on_change: Optional[Callable[[bool], None]] = None)Construct a container widget.
Containers can be used as context managers to build nested UI:
with tg.Container():
tg.Button("Child")Container layout configuration:
set_layout(tg.LayoutMode.Column | Row | Grid | None)set_align(tg.Align.Start | Center | End | Stretch)set_justify(tg.Justify.Start | Center | End | SpaceBetween)set_gap(int)set_grid_columns(int)(for grids)
Convenience factories:
tg.Row()tg.Column()tg.Grid(columns)tg.Absolute()(layout disabled; keepsset_positionplacements)
Scrollable container widget. Use it as a context manager to add children, and scroll with the mouse wheel when the cursor is over it.
Signature:
ScrollView()Methods:
set_scroll_y(int)scroll_by(dy: int)Properties:scroll_y: int(read-only)
Construct a 2D canvas widget that records draw commands and renders them each frame.
Methods:
clear()draw_line(x1, y1, x2, y2, color="#FFFFFF", thickness=1)draw_rect(x, y, w, h, color="#FFFFFF", radius=0, filled=True, thickness=1)draw_circle(cx, cy, radius, color="#FFFFFF", filled=True, thickness=1)draw_text(x, y, text, color="#FFFFFF")
Reactive integer state container.
Methods:
get() -> intset(value: int) -> Nonesubscribe(callback: Callable[[int], None]) -> None
Other state types:
StateFloatStateBoolStateString
Note: state changes do not automatically rebuild your widget tree; use subscribe(...) to update existing widget instances (for example, calling label.set_text(...)).
Subsystems:
- Core: configuration, app orchestration, timing, UUID generation
- Window: Win32 window, input events, DPI helpers
- Graphics: internal renderer and GPU abstraction placeholders
- Widgets: widget tree and primitive controls
- Layout: basic flex-like vertical stacking
- Style: theming and visual properties
- Animation: property tween bookkeeping
- State: reactive integer state
- Async: background job runner
- Plugin: dynamic module placeholder
- System: logging and profiler
Primary import:
import truegraphics as tgTypical app:
import truegraphics as tg
app = tg.App()
counter = tg.StateInt(0)
label = None
@app.window
def main():
global label
def update_label(value: int):
if label is not None:
label.set_text(f"Count: {value}")
counter.subscribe(update_label)
tg.Button("Increment", on_click=lambda: counter.set(counter.get() + 1))
label = tg.Label(f"Count: {counter.get()}")
app.run()Interactive clickable widget with hover-aware style fields and click callback.
Text display widget.
Root/group widget for child composition.
Custom drawing placeholder.
Layouts are configured by container widgets:
tg.Column()(default for containers): stacks children verticallytg.Row(): lays out children horizontallytg.Grid(cols): lays out children into a fixed column gridtg.Absolute(): disables layout for that container (children keep theirset_positionvalues)
Layout applies recursively and re-runs on window resize.
The repository contains an animation subsystem (tween bookkeeping), but it is not currently integrated into the Python-facing runtime loop (there is no public Python API for animations yet).
Colors can be provided as "#RRGGBB" / "#RRGGBBAA" or (r, g, b) / (r, g, b, a) tuples.
Common styling calls:
btn = tg.Button("OK")
btn.set_background("#3A7AFE")
btn.set_text_color("#FFFFFF")
btn.set_border_radius(8)
btn.set_border_width(1)
btn.set_border_color("#1F2937")
btn.set_padding(10)
btn.set_margin(6)truegraphics.Image draws an image loaded from disk (PNG/JPG/etc) using Windows GDI+.
Signature:
Image(path: str = "")Methods:
set_source(path: str)
Animations (numeric widget properties):
btn = tg.Button("Move me")
btn.animate("x", 300, duration=0.5)Supported properties: "x", "y", "width", "height".
Timers:
app.set_timeout(1.0, lambda: print("one second"))
timer_id = app.set_interval(0.5, lambda: print("tick"))
app.clear_timer(timer_id)Async:
def work():
# do slow work here
pass
app.run_async(work, on_done=lambda: print("done"))Clipboard helpers:
tg.clipboard_set_text("hello")
print(tg.clipboard_get_text())TextBox supports Ctrl+C/Ctrl+X/Ctrl+V (whole-text copy/cut/paste for now).
App shortcuts:
app.on_shortcut("Ctrl+S", lambda: print("save"))Slider(min=0.0, max=1.0, value=0.0, on_change=None):
tg.Slider(0, 100, 25, on_change=lambda v: print(v))ProgressBar(value=0.0):
bar = tg.ProgressBar(0.3)
bar.value = 0.7Dropdown(items=[], selected=0, on_change=None):
tg.Dropdown(["Low", "Medium", "High"], selected=1, on_change=lambda i: print(i))Tabs() with pages created by tabs.tab(title):
tabs = tg.Tabs()
with tabs.tab("One"):
tg.Label("Tab one")
with tabs.tab("Two"):
tg.Label("Tab two")RadioButton(text="", group="default", checked=False, on_change=None):
tg.RadioButton("Option A", group="mode", checked=True)
tg.RadioButton("Option B", group="mode")TextArea(text=""):
ta = tg.TextArea("Line 1\nLine 2")
ta.set_size(520, 220)PasswordBox(text=""):
tg.PasswordBox("secret")ListView(items=[], on_select=None):
tg.ListView(["One", "Two", "Three"], on_select=lambda i: print("selected", i))Table(headers=[], rows=[]):
tg.Table(["Name", "Value"], [["A", "1"], ["B", "2"]])TreeView(items=[], on_select=None) where items are (text, level) pairs:
items = [("Root", 0), ("Child 1", 1), ("Child 2", 1)]
tg.TreeView(items, on_select=lambda i: print("selected", i))ScrollView():
scroll = tg.ScrollView()
scroll.set_size(520, 240)
with scroll:
for i in range(30):
tg.Label(f"Row {i}")Horizontal scroll: hold Shift while scrolling the mouse wheel.
tg.message_box("Hello", "Title")
path = tg.open_file_dialog()
save = tg.save_file_dialog()Resource paths:
tg.add_resource_path("assets")
print(tg.resolve_resource("logo.png"))Load a font file (process-private) and use it by family name:
tg.load_font("assets/MyFont.ttf")
lbl = tg.Label("Hello")
lbl.set_font("My Font Family Name")
lbl.set_font_size(18)Register a file-drop callback on any widget:
label = tg.Label("Drop files here")
label.on_drop_files(lambda files: label.set_text(str(files)))Additional windows (registered before run()):
app = tg.App()
@app.window
def main():
tg.Label("Main")
def second():
tg.Label("Second window")
app.add_window(second, title="Second", width=420, height=220)
app.run()System tray icon:
app = tg.App()
app.enable_tray("assets/app.ico", "TrueGraphics", on_click=lambda: tg.message_box("clicked", "tray"))
@app.window
def main():
tg.Label("Running")
app.run()- No IME / complex text shaping.
- Text measurement/wrapping is not layout-aware yet.
- Accessibility is not implemented.
Plugins and async tasks have dedicated engine modules so the architecture can scale without breaking the public Python API.