Objects#
Objects are the core building blocks of a VIStk application. Import from VIStk.Objects.
Root#
Root(Tk, Window) — The application’s main window. Wraps Tk with VIStk attributes.
See also Host — a subclass of Root that adds persistent tray-based lifecycle, tabbed screen management, and unified navigation.
from VIStk.Objects import Root
root = Root()
Attributes:
Attribute |
Type |
Description |
|---|---|---|
|
|
Set to |
|
|
Geometry helper attached to this window |
|
|
Layout manager for this window |
|
|
The loaded VIS project |
Methods:
Method |
Description |
|---|---|
|
Sets the window title and marks the active screen in |
|
Cleanly destroys all child widgets and sets |
|
Registers a function to call after the main loop exits — use for screen redirects. |
|
Executes the registered exit action. |
|
Maximizes the window (zoomed, not absolute fullscreen). |
|
Restores the window to normal size. |
|
Sets the window icon from |
Typical pattern:
root = Root()
root.screenTitle("Home")
root.WindowGeometry.setGeometry(width=1024, height=768, align="center")
root.fullscreen()
# build UI here
while root.Active:
root.update()
Host#
Host — The application host. Owns a hidden Tk() root window and manages one or more
visible DetachedWindow instances. The Host is not a subclass of Root — it is a
standalone class that coordinates window lifecycle, screen loading, and menu configuration.
The hidden root is never shown to the user. All visible UI lives inside DetachedWindow
instances, each of which contains its own HostMenu, SplitView (with TabManager
panes), and InfoRow.
On the first call to update(), the Host automatically opens the project’s default screen
(from project.json). This deferred open ensures that Host.py has time to configure
default_menu_setup before any window is created.
from VIStk.Objects import Host
from modules.menu import shared_menu_structure
host = Host()
host.default_menu_setup = lambda m: m.build_shared_menu(shared_menu_structure())
while host.Active:
host.tick_fps()
host.update()
Attributes:
Attribute |
Type |
Description |
|---|---|---|
|
|
|
|
|
The hidden Tk root. All |
|
|
The loaded VIS project. |
|
|
All live DetachedWindow instances. |
|
|
All active TabManager panes across all windows. |
|
|
The most recently focused pane. |
|
|
Called on every new |
|
|
Current frames per second, updated by |
Methods:
Method |
Description |
|---|---|
|
Unified navigation. Tabbed screens open as tabs in the active window; standalone
screens open as new |
|
Processes all pending Tk events for the root and every |
|
Call once per loop iteration to maintain |
|
Closes all |
|
Removes the Host from the Windows startup registry. |
Singleton#
Host.__init__ sets VIStk.Objects._Host._HOST_INSTANCE = self. Project.open() checks
this reference to route navigation. Only one Host should exist per process.
TabManager#
TabManager(Frame) — Manages the tabbed screen area inside the Host window. Created
automatically by Host.__init__ and exposed as host.TabManager. It owns a TabBar strip
along the top edge and a content area where each tab’s Frame lives.
Screen modules are imported by the Host and passed to open_tab. TabManager calls
setup(frame), on_focused(), and on_unfocused() at the appropriate times.
Hook lookup priority: If modules/<screen>/m_<screen>.py exists, TabManager checks it
first for on_focused, on_unfocused, and configure_menu. The screen script is used as a
fallback.
Attributes:
Attribute |
Type |
Description |
|---|---|---|
|
|
The tab strip widget |
|
|
Name of the currently focused tab |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Methods:
Method |
Returns |
Description |
|---|---|---|
|
|
Open a new tab. If already open, focuses it instead. |
|
|
Close the named tab, running |
|
|
Focus the named tab. |
|
|
Whether a tab with this name is open. |
|
|
Close and reopen at the same position, re-running |
|
|
Set the info string for the tab. Accepts a plain string or |
TabManager is not normally used directly — host.open() handles all navigation.
DetachedWindow#
DetachedWindow — A floating Toplevel window containing its own SplitView (which wraps
one or more TabManager panes). Created by the Host when a tab is popped out via the right-click
context menu or drag-to-detach. Tracked in host._detached.
Popping a tab out re-runs setup(parent) in the new window, so screen UI state is reset.
Attributes:
dw._split_view—SplitViewmanaging the window’s content areadw.tab_manager— property returningdw._split_view.focused_panedw.HostMenu— menu bar (shared cascades cloned from Host)dw.InfoRow— status bar
Behaviour:
Right-clicking a tab and choosing Open in new window sends the tab back to the main Host.
Dragging a tab and releasing it outside all bars creates a new
DetachedWindow.Dragging a tab from one bar into another registered
TabBarmerges it there.Dragging a tab into a split zone (edge or center) of any pane in any window creates a split or adds the tab to the target pane — cross-window drag-to-split is fully supported.
Force refresh re-imports the screen module and re-runs
setup(parent)in-place.Closing the window runs
on_unfocusedon all tabs across all panes and destroys them.When the Host shuts down, all
DetachedWindowinstances are closed first.
DetachedWindow is created internally — you do not instantiate it directly.
SubRoot#
SubRoot(Toplevel, Window) — A popup or secondary window. Wraps Toplevel with VIStk
attributes.
from VIStk.Objects import SubRoot
popup = SubRoot()
Attributes:
Attribute |
Type |
Description |
|---|---|---|
|
|
Geometry helper for this window |
|
|
Layout manager for this window |
|
|
|
Methods:
Method |
Description |
|---|---|
|
Makes the window modal — blocks input to the parent until this window is closed. Cannot be undone. |
QuestionWindow and WarningWindow are both subclasses of SubRoot.
Window#
Window is a mixin class inherited by both Root and SubRoot. It provides fullscreen
control and icon loading. You do not instantiate it directly.
Methods:
Method |
Description |
|---|---|
|
Maximizes the window. |
|
Restores window size. |
|
Loads |
WindowGeometry#
WindowGeometry handles window sizing and positioning. It is automatically attached to Root
and SubRoot as self.WindowGeometry.
getGeometry#
getGeometry(respect_size=False)
Reads the current geometry from the window and stores it internally. If respect_size=True,
uses the actual rendered size (winfo_width/height) instead of the geometry string.
setGeometry#
setGeometry(width, height, x, y, align, size_style, window_ref)
Positions and sizes the window.
Parameter |
Type |
Description |
|---|---|---|
|
|
Width in pixels (or percentage if |
|
|
Height in pixels (or percentage if |
|
|
X position in pixels. Ignored if |
|
|
Y position in pixels. Ignored if |
|
|
Named alignment: |
|
|
|
|
|
Reference window for |
Examples:
# Center an 800x600 window on screen
root.WindowGeometry.setGeometry(width=800, height=600, align="center")
# Center a popup on its parent window — flicker-free (0.5.0+)
from VIStk.Objects import WindowGeometry
WindowGeometry(popup)
# ... build all child widgets first ...
popup.WindowGeometry.center_on(root)
Note
The pre-0.5.0 multi-call pattern (popup.update() →
getGeometry(True) → setGeometry(align="center", ...)) made the
popup briefly visible at the OS default position before jumping to
the centred position. center_on() performs the same math
inside a withdraw() / deiconify() wrap and uses
update_idletasks() (layout-only) instead of update(), so the
window is never drawn at its default position.
Do not call center_on on the root Tk() window — withdraw()
on the main application window hides it entirely.
center_on (0.5.0)#
center_on(window_ref)
Centre this window on window_ref without a visible flicker. Drop-in
replacement for the multi-call update + getGeometry + setGeometry
pattern. Call after all child widgets are built so winfo_width /
winfo_height reflect the final size.
popup = Toplevel(root)
Button(popup, text="OK", command=popup.destroy).pack(padx=50, pady=50)
from VIStk.Objects import WindowGeometry
WindowGeometry(popup)
popup.WindowGeometry.center_on(root)
stripGeometry#
stripGeometry(objects)
Returns raw integer values from the current geometry string.
x, y = root.WindowGeometry.stripGeometry(("x", "y"))
w, h, x, y = root.WindowGeometry.stripGeometry("all")
Layout#
Layout is a proportional grid system for placing frames inside a window or frame using
place(). Rows and columns are defined as fractions that sum to 1.0.
from VIStk.Objects import Layout
layout = Layout(frame)
layout.rowSize([0.1, 0.8, 0.1]) # 10% header, 80% body, 10% footer
layout.colSize([0.25, 0.75]) # 25% sidebar, 75% content
rowSize#
rowSize(rows, minsize=None, maxsize=None)
Sets row proportions. Each value is a float from 0.0 to 1.0; they must sum to exactly 1.0.
minsize and maxsize are optional lists of pixel constraints stored as row_min /
row_max.
layout.rowSize([0.5, 0.5])
layout.rowSize([0.1, 0.7, 0.2])
layout.rowSize([0.1, 0.8, 0.1], minsize=[30, 100, 30])
colSize#
colSize(columns, minsize=None, maxsize=None)
Sets column proportions. Same rules as rowSize. Optional minsize / maxsize stored as
col_min / col_max.
layout.colSize([1.0])
layout.colSize([0.3, 0.7])
layout.colSize([0.25, 0.75], minsize=[150, None])
cell#
cell(row, column, rowspan=None, columnspan=None, padding=0)
Returns a dict of place() kwargs for the given cell. Pass directly to
widget.place(**...). Rows and columns are 0-indexed. The optional padding argument adds
inward pixel padding on all sides.
header = Frame(root)
header.place(**root.Layout.cell(0, 0))
# Span multiple cells
panel = Frame(root)
panel.place(**root.Layout.cell(1, 0, columnspan=2))
# 8px padding inside the cell
card = Frame(root)
card.place(**root.Layout.cell(1, 1, padding=8))
apply#
apply(widget, row, col, rowspan=None, columnspan=None, padding=0)
Places widget in the given cell using absolute pixel coordinates and automatically re-places it
whenever the parent frame is resized. Unlike cell(), apply() enforces any minsize /
maxsize constraints set via rowSize() / colSize().
layout.rowSize([0.1, 0.8, 0.1], minsize=[30, 100, 30])
layout.colSize([0.3, 0.7])
layout.apply(header_frame, row=0, col=0)
layout.apply(body_frame, row=1, col=0, rowspan=1)
Layout is available on Root as root.Layout and on SubRoot as popup.Layout. It
is also the basis for LayoutFrame.
LayoutFrame#
LayoutFrame(Frame) — A standard Tkinter Frame with a Layout object pre-attached as
self.Layout. Use it when you need to subdivide a frame using proportional placement.
from VIStk.Widgets import LayoutFrame
main_area = LayoutFrame(root)
main_area.place(**root.Layout.cell(1, 0))
main_area.Layout.colSize([0.4, 0.6])
main_area.Layout.rowSize([1.0])
left_panel = Frame(main_area)
left_panel.place(**main_area.Layout.cell(0, 0))
right_panel = Frame(main_area)
right_panel.place(**main_area.Layout.cell(0, 1))
VIMG#
VIMG loads and optionally auto-resizes images for Tkinter widgets using PIL. Images are loaded
from the project’s Images/ folder by default.
from VIStk.Objects import VIMG
img = VIMG(label_widget, "logo.png")
label_widget.configure(image=img.holder.image)
Constructor:
Parameter |
Type |
Description |
|---|---|---|
|
|
The widget that will display the image |
|
|
Filename in |
|
|
If |
|
|
Fixed |
|
|
If provided, the image resizes to fit this widget whenever it is resized. |
Auto-resize example:
# Image fills a label and resizes with the window
img_label = Label(root)
img_label.place(**root.Layout.cell(0, 0))
img = VIMG(img_label, "background", fill=img_label)
ArgHandler#
ArgHandler parses command-line arguments passed to a screen script. Each flag is registered
with a keyword and a callback function. Flags are passed with -- on the command line.
from VIStk.Objects import ArgHandler
import sys
handler = ArgHandler()
handler.newFlag("load", lambda args: load_record(args[0]))
handler.newFlag("mode", lambda args: set_mode(args[0]))
handler.handle(sys.argv)
Command line usage:
python myscreen.py --load 1042 --mode readonly
Methods:
Method |
Description |
|---|---|
|
Registers a flag. Accepts |
|
Parses |
The ArgHandler on Root.Project is used internally by the CLI for screen loading with
arguments.
open_active_screen_docs (0.5.0)#
Reads the active screen from the in-process Host singleton, runs
Project.resolve_docs_url() (active screen docs -> project
defaults.docs -> None), and hands the URL to
webbrowser.open(). Returns True on dispatch, False if no
URL is configured.
Intended to be wired into HostMenu.add_project_command for a
one-line top-level Help button:
from VIStk.Widgets import HostMenu
from VIStk.Objects import open_active_screen_docs
host_menu.add_project_command("Help", open_active_screen_docs)
The URL is taken verbatim from project.json; configure entries via
VIS docs set ... (see CLI Reference).