# ============================================================ # fltk — Viper 的 FLTK GUI 绑定包(对接 cfltk C API) # # 用户用法: # import fltk # win = fltk.Fl_Window(400, 300, "Hello") # box = fltk.Fl_Box(10, 10, 380, 40, "Hello, World!") # btn = fltk.Fl_Button(150, 100, 100, 30, "Click") # win.end() # win.show() # fltk.Fl.run() # # 说明: # * 本包只做 extern FFI(fltk._cfl* 模块)+ 少量 Pythonic 包装类; # 所有 FLTK 对象都是不透明指针,方法即 cfltk 的 Fl_<类>_<动作>。 # * 完整 C API 通过 `from fltk._cfl import *` 等直接可用。 # * 回调支持:Viper 模块级函数可直接作为 Fl_Callback 传给 FLTK—— # TPV 把函数名自动 bitcast 成函数指针(如 CreateThread 传函数)。 # 回调签名约定: def cb(w: bytes, data: bytes): ...(w=控件指针,data=用户数据) # def on_click(w: bytes, data: bytes): # Fl_Widget_set_label(w, "Clicked!") # btn.set_callback(on_click, 0) # Fl.add_timeout(1.0, on_tick, 0) # * 事件驱动也可用 Fl.check()/Fl.event*() 轮询。 # ============================================================ import t, c from fltk._types import * from fltk._enums import * from fltk._cfl import * from fltk._cfl_widget import * from fltk._cfl_box import * from fltk._cfl_button import * from fltk._cfl_window import * from fltk._cfl_input import * from fltk._cfl_text import * from fltk._cfl_group import * from fltk._cfl_valuator import * from fltk._cfl_menu import * from fltk._cfl_dialog import * from fltk._cfl_image import * from fltk._cfl_draw import * from fltk._cfl_misc import * from fltk._cfl_browser import * from fltk._cfl_table import * from fltk._cfl_tree import * from fltk._cfl_term import * from fltk._cfl_prefs import * from fltk._cfl_printer import * from fltk._cfl_surface import * from fltk._cfl_utils import * from fltk._cfl_lock import * from fltk._cfl_theme import * # ============================================================ # Fl — FLTK 全局静态类(事件循环 / 事件 / 颜色) # ============================================================ @t.NoVTable class Fl: """FLTK 全局函数集合(静态方法)""" @staticmethod def run() -> int: return Fl_run() @staticmethod def check() -> int: return Fl_check() @staticmethod def wait() -> int: return Fl_wait() @staticmethod def wait_for(timeout: t.CDouble) -> t.CDouble: return Fl_wait_for(timeout) @staticmethod def flush(): Fl_flush() @staticmethod def redraw(): Fl_redraw() @staticmethod def lock() -> int: return Fl_lock() @staticmethod def unlock(): Fl_unlock() @staticmethod def event() -> int: return Fl_event() @staticmethod def event_x() -> int: return Fl_event_x() @staticmethod def event_y() -> int: return Fl_event_y() @staticmethod def event_button() -> int: return Fl_event_button() @staticmethod def event_key() -> int: return Fl_event_key() @staticmethod def event_text() -> str: return Fl_event_text() @staticmethod def event_length() -> int: return Fl_event_length() @staticmethod def event_state() -> int: return Fl_event_state() @staticmethod def event_inside(x: int, y: int, w: int, h: int) -> int: return Fl_event_inside(x, y, w, h) @staticmethod def set_scheme(scheme: str) -> int: """切换全局风格 scheme。 内置风格: 'base' / 'plastic' / 'gtk+' / 'gleam' / 'oxy'。 调用后 FLTK 自动重载并重绘所有窗口。 用法: fltk.Fl.set_scheme("plastic")""" return Fl_set_scheme(scheme) @staticmethod def visible_focus() -> int: return Fl_visible_focus() @staticmethod def set_visible_focus(v: int): Fl_set_visible_focus(v) @staticmethod def get_rgb_color(r: t.CUInt8T, g: t.CUInt8T, b: t.CUInt8T) -> t.CUInt32T: return Fl_get_rgb_color(r, g, b) @staticmethod def set_color(c: t.CUInt32T, r: t.CUInt8T, g: t.CUInt8T, b: t.CUInt8T): Fl_set_color(c, r, g, b) @staticmethod def first_window() -> Fl_WindowPtr: return Fl_first_window() @staticmethod def next_window(win: Fl_WindowPtr) -> Fl_WindowPtr: return Fl_next_window(win) @staticmethod def set_font_size(size: int): Fl_set_font_size(size) @staticmethod def font_size() -> int: return Fl_font_size() @staticmethod def set_scrollbar_size(sz: int): Fl_set_scrollbar_size(sz) @staticmethod def scrollbar_size() -> int: return Fl_scrollbar_size() @staticmethod def scheme() -> int: return Fl_scheme() @staticmethod def scheme_string() -> str: """当前风格名('base'/'plastic'/'gtk+'/'gleam'/'oxy')。""" return Fl_scheme_string() @staticmethod def reload_scheme() -> int: """重载当前风格(修改背景/前景色后调用生效)。""" return Fl_reload_scheme() @staticmethod def set_background(r: int, g: int, b: int): """设置全局背景色(0~255),之后需 Fl.reload_scheme()。""" Fl_background(r, g, b) @staticmethod def set_background2(r: int, g: int, b: int): """设置全局次级背景色(0~255)。""" Fl_background2(r, g, b) @staticmethod def set_foreground(r: int, g: int, b: int): """设置全局前景色(文字,0~255)。""" Fl_foreground(r, g, b) # ----- Fl_Theme 主题(C++ 主题库,libfltk_theme.a) ----- @staticmethod def set_theme_dark(): """应用 Fl_Theme 深色主题(flat 控件 + BLACK 色板 + 深灰背景/白前景)。""" Fl_Theme_apply_dark() @staticmethod def set_theme_metro(): """应用 Fl_Theme Metro 主题(metro 控件 + 蓝灰配色)。""" Fl_Theme_apply_metro() @staticmethod def set_border_radius(r: int): """设置 flat 控件圆角半径(默认 5;需在应用主题前调用)。""" Fl_Theme_set_border_radius(r) @staticmethod def apply_flat_scheme(): """仅应用 flat 控件绘制方案(不改颜色)。""" Fl_Theme_apply_flat_scheme() @staticmethod def apply_metro_scheme(): """仅应用 metro 控件绘制方案(不改颜色)。""" Fl_Theme_apply_metro_scheme() # ----- 定时器 / 线程唤醒 ----- @staticmethod def add_timeout(seconds: t.CDouble, cb: bytes, data: bytes = 0): """注册一次性定时回调(seconds 秒后触发)。回调签名: def cb(w: bytes, data: bytes)""" Fl_add_timeout(seconds, cb, data) @staticmethod def repeat_timeout(seconds: t.CDouble, cb: bytes, data: bytes = 0): """注册重复定时回调(每 seconds 秒触发,回调内需再调 repeat_timeout 保持)。""" Fl_repeat_timeout(seconds, cb, data) @staticmethod def awake(): """唤醒另一线程的 Fl.run/Fl.wait 事件循环。""" Fl_awake() @staticmethod def awake_callback(handler: bytes, data: bytes = 0) -> int: """注册跨线程唤醒回调(另一线程 Fl.awake() 后主循环调用 handler)。""" return Fl_awake_callback(handler, data) # ----- 补全事件查询 ----- @staticmethod def event_original_key() -> int: return Fl_event_original_key() @staticmethod def event_clicks() -> int: return Fl_event_clicks() @staticmethod def event_x_root() -> int: return Fl_event_x_root() @staticmethod def event_y_root() -> int: return Fl_event_y_root() @staticmethod def event_dx() -> int: return Fl_event_dx() @staticmethod def event_dy() -> int: return Fl_event_dy() @staticmethod def event_is_click() -> int: return Fl_event_is_click() @staticmethod def event_key_down(k: int) -> int: return Fl_event_key_down(k) # ============================================================ # Fl_Widget — 控件基类包装 # ============================================================ @t.NoVTable class Fl_Widget: """FLTK 控件基类(不透明指针包装)""" _ptr: Fl_WidgetPtr def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Widget_new(x, y, w, h, label) def x(self) -> int: return Fl_Widget_x(self._ptr) def y(self) -> int: return Fl_Widget_y(self._ptr) def width(self) -> int: return Fl_Widget_width(self._ptr) def height(self) -> int: return Fl_Widget_height(self._ptr) def label(self) -> str: return Fl_Widget_label(self._ptr) def set_label(self, label: str): Fl_Widget_set_label(self._ptr, label) def show(self): Fl_Widget_show(self._ptr) def hide(self): Fl_Widget_hide(self._ptr) def activate(self): Fl_Widget_activate(self._ptr) def deactivate(self): Fl_Widget_deactivate(self._ptr) def redraw(self): Fl_Widget_redraw(self._ptr) def resize(self, x: int, y: int, w: int, h: int): Fl_Widget_resize(self._ptr, x, y, w, h) def set_color(self, color: t.CUInt32T): Fl_Widget_set_color(self._ptr, color) def color(self) -> t.CUInt32T: return Fl_Widget_color(self._ptr) def set_box(self, box: int): Fl_Widget_set_box(self._ptr, box) def box(self) -> int: return Fl_Widget_box(self._ptr) def set_align(self, align: int): Fl_Widget_set_align(self._ptr, align) def align(self) -> int: return Fl_Widget_align(self._ptr) def set_tooltip(self, tip: str): Fl_Widget_set_tooltip(self._ptr, tip) def tooltip(self) -> str: return Fl_Widget_tooltip(self._ptr) def parent(self) -> Fl_WidgetPtr: return Fl_Widget_parent(self._ptr) def window(self) -> Fl_WindowPtr: return Fl_Widget_window(self._ptr) def visible(self) -> int: return Fl_Widget_visible(self._ptr) def active(self) -> int: return Fl_Widget_active(self._ptr) def delete(self): Fl_Widget_delete(self._ptr) # ----- 回调 ----- def set_callback(self, cb: bytes, data: bytes = 0): """注册控件回调(如点击/变更触发)。cb 传 Viper 模块级函数名,自动转函数指针。 回调签名: def cb(w: bytes, data: bytes): ...(w=控件指针,可转回本类指针用)。 触发时机由 set_when 控制(默认 Fl_WHEN_RELEASE)。""" Fl_Widget_set_callback(self._ptr, cb, data) def callback(self) -> bytes: return Fl_Widget_callback(self._ptr) def do_callback(self): """手动触发本控件回调(不经过事件循环)。""" Fl_Widget_do_callback(self._ptr) def set_when(self, when: int): """设置回调触发条件(Fl_WHEN_* 常量见 _enums.vp)。""" Fl_Widget_set_when(self._ptr, when) def when(self) -> int: return Fl_Widget_when(self._ptr) def set_user_data(self, data: bytes): """设置回调用户数据(回调的第二个参数 data)。""" Fl_Widget_set_user_data(self._ptr, data) def user_data(self) -> bytes: return Fl_Widget_user_data(self._ptr) def set_image(self, img: bytes): """设置控件图标(传 Fl_PNG_Image 等图片对象的 _ptr)。""" Fl_Widget_set_image(self._ptr, img) def image(self) -> bytes: return Fl_Widget_image(self._ptr) # ============================================================ # Fl_Window — 窗口包装 # ============================================================ @t.NoVTable class Fl_Window(Fl_Widget): """FLTK 窗口""" def __init__(self, w: int, h: int, title: str = ""): self._ptr = Fl_Window_new(0, 0, w, h, title) def begin(self): Fl_Window_begin(self._ptr) def end(self): Fl_Window_end(self._ptr) def set_modal(self, flag: t.CUInt32T): Fl_Window_make_modal(self._ptr, flag) def fullscreen(self, flag: t.CUInt32T): Fl_Window_fullscreen(self._ptr, flag) def make_current(self): Fl_Window_make_current(self._ptr) def set_border(self, flag: int): Fl_Window_set_border(self._ptr, flag) def border(self) -> int: return Fl_Window_border(self._ptr) def iconize(self): Fl_Window_iconize(self._ptr) def free_position(self): Fl_Window_free_position(self._ptr) def shown(self) -> int: return Fl_Window_shown(self._ptr) def set_xclass(self, xc: str): Fl_Window_set_xclass(self._ptr, xc) def x_root(self) -> int: return Fl_Window_x_root(self._ptr) def y_root(self) -> int: return Fl_Window_y_root(self._ptr) def size_range(self, minw: int, minh: int, maxw: int, maxh: int): Fl_Window_size_range(self._ptr, minw, minh, maxw, maxh) def set_cursor(self, cursor: int): Fl_Window_set_cursor(self._ptr, cursor) def resize(self, x: int, y: int, w: int, h: int): Fl_Window_resize(self._ptr, x, y, w, h) # ============================================================ # Fl_Box — 静态文本/装饰框 # ============================================================ @t.NoVTable class Fl_Box(Fl_Widget): """FLTK 文本框/装饰框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Box_new(x, y, w, h, label) # ============================================================ # Fl_Button — 按钮包装 # ============================================================ @t.NoVTable class Fl_Button(Fl_Widget): """FLTK 按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Button_new(x, y, w, h, label) def value(self) -> int: return Fl_Button_value(self._ptr) def set_value(self, v: int): Fl_Button_set_value(self._ptr, v) def set(self): Fl_Button_set_value(self._ptr, 1) def clear(self) -> int: return Fl_Button_clear(self._ptr) def set_shortcut(self, s: int): Fl_Button_set_shortcut(self._ptr, s) def shortcut(self) -> int: return Fl_Button_shortcut(self._ptr) def set_down_box(self, box: int): Fl_Button_set_down_box(self._ptr, box) def down_box(self) -> int: return Fl_Button_down_box(self._ptr) @t.NoVTable class Fl_Check_Button(Fl_Button): """FLTK 复选框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Check_Button_new(x, y, w, h, label) def is_checked(self) -> int: return Fl_Check_Button_is_checked(self._ptr) def set_checked(self, checked: int): Fl_Check_Button_set_checked(self._ptr, checked) @t.NoVTable class Fl_Radio_Button(Fl_Button): """FLTK 单选按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Radio_Button_new(x, y, w, h, label) def is_toggled(self) -> int: return Fl_Radio_Button_is_toggled(self._ptr) def toggle(self, v: int): Fl_Radio_Button_toggle(self._ptr, v) @t.NoVTable class Fl_Repeat_Button(Fl_Button): """FLTK 重复触发按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Repeat_Button_new(x, y, w, h, label) @t.NoVTable class Fl_Return_Button(Fl_Button): """FLTK 回车按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Return_Button_new(x, y, w, h, label) @t.NoVTable class Fl_Light_Button(Fl_Button): """FLTK 指示灯按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Light_Button_new(x, y, w, h, label) def is_on(self) -> int: return Fl_Light_Button_is_on(self._ptr) def turn_on(self, v: int): Fl_Light_Button_turn_on(self._ptr, v) # ============================================================ # Fl_Input / Fl_Output — 文本输入输出 # ============================================================ @t.NoVTable class Fl_Input(Fl_Widget): """FLTK 单行文本输入框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Input_new(x, y, w, h, label) def value(self) -> str: return Fl_Input_value(self._ptr) def set_value(self, text: str): Fl_Input_set_value(self._ptr, text) def set_maximum_size(self, m: int): Fl_Input_set_maximum_size(self._ptr, m) def maximum_size(self) -> int: return Fl_Input_maximum_size(self._ptr) def set_readonly(self, v: int): Fl_Input_set_readonly(self._ptr, v) def readonly(self) -> int: return Fl_Input_readonly(self._ptr) @t.NoVTable class Fl_Output(Fl_Widget): """FLTK 单行文本输出框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Output_new(x, y, w, h, label) def value(self) -> str: return Fl_Output_value(self._ptr) def set_value(self, text: str) -> int: return Fl_Output_set_value(self._ptr, text) @t.NoVTable class Fl_Int_Input(Fl_Input): def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Int_Input_new(x, y, w, h, label) @t.NoVTable class Fl_Float_Input(Fl_Input): def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Float_Input_new(x, y, w, h, label) # ============================================================ # Fl_Text_Buffer / Fl_Text_Display — 多行文本 # ============================================================ @t.NoVTable class Fl_Text_Buffer: """FLTK 文本缓冲""" _ptr: Fl_Text_BufferPtr def __init__(self): self._ptr = Fl_Text_Buffer_new() def text(self) -> str: return Fl_Text_Buffer_text(self._ptr) def set_text(self, text: str): Fl_Text_Buffer_set_text(self._ptr, text) def append(self, text: str): Fl_Text_Buffer_append(self._ptr, text) def length(self) -> int: return Fl_Text_Buffer_length(self._ptr) def insert(self, pos: int, text: str): Fl_Text_Buffer_insert(self._ptr, pos, text) def remove(self, start: int, end: int): Fl_Text_Buffer_remove(self._ptr, start, end) def save_file(self, path: str) -> int: return Fl_Text_Buffer_save_file(self._ptr, path) def load_file(self, path: str) -> int: return Fl_Text_Buffer_load_file(self._ptr, path) def free(self): Fl_Text_Buffer_delete(self._ptr) @t.NoVTable class Fl_Text_Display(Fl_Widget): """FLTK 多行文本显示""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Text_Display_new(x, y, w, h, label) def set_buffer(self, buf: Fl_Text_BufferPtr): Fl_Text_Display_set_buffer(self._ptr, buf) def set_text_font(self, font: int): Fl_Text_Display_set_text_font(self._ptr, font) def set_text_size(self, size: int): Fl_Text_Display_set_text_size(self._ptr, size) def set_text_color(self, color: t.CUInt32T): Fl_Text_Display_set_text_color(self._ptr, color) def set_scrollbar_size(self, size: int): Fl_Text_Display_set_scrollbar_size(self._ptr, size) # ============================================================ # Fl_Group — 容器包装 # ============================================================ @t.NoVTable class Fl_Group(Fl_Widget): """FLTK 控件组""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Group_new(x, y, w, h, label) def begin(self): Fl_Group_begin(self._ptr) def end(self): Fl_Group_end(self._ptr) def add(self, wid: Fl_WidgetPtr): Fl_Group_add(self._ptr, wid) def remove(self, wid: Fl_WidgetPtr): Fl_Group_remove(self._ptr, wid) def clear(self): Fl_Group_clear(self._ptr) def children(self) -> int: return Fl_Group_children(self._ptr) def child(self, index: int) -> Fl_WidgetPtr: return Fl_Group_child(self._ptr, index) def set_resizable(self, wid: Fl_WidgetPtr): Fl_Group_resizable(self._ptr, wid) @t.NoVTable class Fl_Scroll(Fl_Group): """FLTK 滚动容器""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Scroll_new(x, y, w, h, label) def set_scrollbar_size(self, size: int): Fl_Scroll_set_scrollbar_size(self._ptr, size) def scrollbar_size(self) -> int: return Fl_Scroll_scrollbar_size(self._ptr) def scroll_to(self, x: int, y: int): Fl_Scroll_scroll_to(self._ptr, x, y) def xposition(self) -> int: return Fl_Scroll_xposition(self._ptr) def yposition(self) -> int: return Fl_Scroll_yposition(self._ptr) @t.NoVTable class Fl_Tabs(Fl_Group): """FLTK 选项卡容器""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Tabs_new(x, y, w, h, label) def value(self) -> Fl_WidgetPtr: return Fl_Tabs_value(self._ptr) def set_value(self, wid: Fl_WidgetPtr): Fl_Tabs_set_value(self._ptr, wid) # ============================================================ # Fl_Slider / Fl_Value_Input / Fl_Value_Output — 数值控件 # ============================================================ @t.NoVTable class Fl_Slider(Fl_Widget): """FLTK 滑动条""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Slider_new(x, y, w, h, label) def value(self) -> t.CDouble: return Fl_Slider_value(self._ptr) def set_value(self, v: t.CDouble): Fl_Slider_set_value(self._ptr, v) def minimum(self) -> t.CDouble: return Fl_Slider_minimum(self._ptr) def set_minimum(self, v: t.CDouble): Fl_Slider_set_minimum(self._ptr, v) def maximum(self) -> t.CDouble: return Fl_Slider_maximum(self._ptr) def set_maximum(self, v: t.CDouble): Fl_Slider_set_maximum(self._ptr, v) def step(self) -> t.CDouble: return Fl_Slider_step(self._ptr) def set_step(self, v: t.CDouble): Fl_Slider_set_step(self._ptr, v) def set_bounds(self, a: t.CDouble, b: t.CDouble): Fl_Slider_set_bounds(self._ptr, a, b) @t.NoVTable class Fl_Value_Input(Fl_Widget): """FLTK 数值输入框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Value_Input_new(x, y, w, h, label) def value(self) -> t.CDouble: return Fl_Value_Input_value(self._ptr) def set_value(self, v: t.CDouble): Fl_Value_Input_set_value(self._ptr, v) def set_bounds(self, a: t.CDouble, b: t.CDouble): Fl_Value_Input_set_bounds(self._ptr, a, b) @t.NoVTable class Fl_Value_Output(Fl_Widget): """FLTK 数值输出框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Value_Output_new(x, y, w, h, label) def value(self) -> t.CDouble: return Fl_Value_Output_value(self._ptr) def set_value(self, v: t.CDouble): Fl_Value_Output_set_value(self._ptr, v) @t.NoVTable class Fl_Progress(Fl_Widget): """FLTK 进度条""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Progress_new(x, y, w, h, label) def value(self) -> t.CDouble: return Fl_Progress_value(self._ptr) def set_value(self, v: t.CDouble): Fl_Progress_set_value(self._ptr, v) def set_minimum(self, v: t.CDouble): Fl_Progress_set_minimum(self._ptr, v) def set_maximum(self, v: t.CDouble): Fl_Progress_set_maximum(self._ptr, v) # ============================================================ # Fl_Choice — 下拉选择 # ============================================================ @t.NoVTable class Fl_Choice(Fl_Widget): """FLTK 下拉选择框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Choice_new(x, y, w, h, label) def add(self, text: str): Fl_Choice_add_choice(self._ptr, text) def value(self) -> int: return Fl_Choice_value(self._ptr) def set_value(self, v: int): Fl_Choice_set_value(self._ptr, v) def text(self, idx: int) -> str: return Fl_Choice_text(self._ptr, idx) # ============================================================ # Fl_Menu_Bar — 菜单栏 # ============================================================ @t.NoVTable class Fl_Menu_Bar(Fl_Widget): """FLTK 菜单栏 add 走 cfltk 完整 6 参签名(name/shortcut/回调/数据/flags), cb 可传 Viper 模块级函数名(回调签名: def cb(w: bytes, data: bytes)); 不传回调(默认)时菜单项无动作。简单下拉建议用 add_choice。""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Menu_Bar_new(x, y, w, h, label) def add(self, path: str, shortcut: int, flags: int, cb: bytes = 0): Fl_Menu_Bar_add(self._ptr, path, shortcut, cb, t.CPtr(0), flags) def add_choice(self, text: str) -> int: return Fl_Menu_Bar_add_choice(self._ptr, text) # ============================================================ # Fl_Native_File_Chooser — 系统文件对话框 # ============================================================ @t.NoVTable class Fl_Native_File_Chooser: """FLTK 原生文件选择对话框 构造需传对话框类型常量(如 Fl_Native_File_Chooser_BROWSE_FILE / BROWSE_DIRECTORY / BROWSE_MULTI_FILE / BROWSE_MULTI_DIRECTORY / BROWSE_SAVE_FILE,见 _enums.vp)。""" _ptr: Fl_Native_File_ChooserPtr def __init__(self, type_: int): self._ptr = Fl_Native_File_Chooser_new(type_) def set_title(self, title: str): Fl_Native_File_Chooser_set_title(self._ptr, title) def set_filter(self, filter_: str): Fl_Native_File_Chooser_set_filter(self._ptr, filter_) def filter(self) -> str: return Fl_Native_File_Chooser_filter(self._ptr) def set_directory(self, dir_: str): Fl_Native_File_Chooser_set_directory(self._ptr, dir_) def directory(self) -> str: return Fl_Native_File_Chooser_directory(self._ptr) def set_preset_file(self, path: str): Fl_Native_File_Chooser_set_preset_file(self._ptr, path) def set_option(self, opt: int): Fl_Native_File_Chooser_set_option(self._ptr, opt) def set_type(self, type_: int): Fl_Native_File_Chooser_set_type(self._ptr, type_) def show(self) -> int: return Fl_Native_File_Chooser_show(self._ptr) def count(self) -> int: return Fl_Native_File_Chooser_count(self._ptr) def filename(self) -> str: return Fl_Native_File_Chooser_filename(self._ptr) def filenames(self, index: int) -> str: return Fl_Native_File_Chooser_filenames(self._ptr, index) def filter_value(self) -> int: return Fl_Native_File_Chooser_filter_value(self._ptr) def set_filter_value(self, v: int): Fl_Native_File_Chooser_set_filter_value(self._ptr, v) def errmsg(self) -> str: return Fl_Native_File_Chooser_errmsg(self._ptr) def delete(self): Fl_Native_File_Chooser_delete(self._ptr) # ============================================================ # 常用别名 # ============================================================ def fltk_init(): """初始化 FLTK(多线程环境需先 Fl_lock 再 init_all)。""" Fl_init_all() # ============================================================ # 补充按钮类 # ============================================================ @t.NoVTable class Fl_Toggle_Button(Fl_Button): """FLTK 切换按钮(按下保持)""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Toggle_Button_new(x, y, w, h, label) @t.NoVTable class Fl_Round_Button(Fl_Button): """FLTK 圆形按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Round_Button_new(x, y, w, h, label) @t.NoVTable class Fl_Radio_Round_Button(Fl_Button): """FLTK 圆形单选按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Radio_Round_Button_new(x, y, w, h, label) @t.NoVTable class Fl_Radio_Light_Button(Fl_Button): """FLTK 指示灯单选按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Radio_Light_Button_new(x, y, w, h, label) @t.NoVTable class Fl_Shortcut_Button(Fl_Button): """FLTK 快捷键录入按钮""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Shortcut_Button_new(x, y, w, h, label) # ============================================================ # 补充输入类 # ============================================================ @t.NoVTable class Fl_Multiline_Input(Fl_Input): """FLTK 多行文本输入框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Multiline_Input_new(x, y, w, h, label) @t.NoVTable class Fl_Secret_Input(Fl_Input): """FLTK 密码输入框(显示为 *)""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Secret_Input_new(x, y, w, h, label) @t.NoVTable class Fl_File_Input(Fl_Input): """FLTK 文件路径输入框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_File_Input_new(x, y, w, h, label) @t.NoVTable class Fl_Multiline_Output(Fl_Output): """FLTK 多行文本输出框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Multiline_Output_new(x, y, w, h, label) # ============================================================ # Fl_Nice_Slider / Fl_Spinner / Fl_Clock # ============================================================ @t.NoVTable class Fl_Nice_Slider(Fl_Slider): """FLTK 美观滑块""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Nice_Slider_new(x, y, w, h, label) @t.NoVTable class Fl_Spinner(Fl_Widget): """FLTK 数字微调框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Spinner_new(x, y, w, h, label) def value(self) -> t.CDouble: return Fl_Spinner_value(self._ptr) def set_value(self, v: t.CDouble): Fl_Spinner_set_value(self._ptr, v) def minimum(self) -> t.CDouble: return Fl_Spinner_minimum(self._ptr) def set_minimum(self, v: t.CDouble): Fl_Spinner_set_minimum(self._ptr, v) def maximum(self) -> t.CDouble: return Fl_Spinner_maximum(self._ptr) def set_maximum(self, v: t.CDouble): Fl_Spinner_set_maximum(self._ptr, v) def step(self) -> t.CDouble: return Fl_Spinner_step(self._ptr) def set_step(self, v: t.CDouble): Fl_Spinner_set_step(self._ptr, v) @t.NoVTable class Fl_Clock(Fl_Widget): """FLTK 时钟(模拟表盘)""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Clock_new(x, y, w, h, label) # ============================================================ # 补充容器类 # ============================================================ @t.NoVTable class Fl_Pack(Fl_Group): """FLTK 自动布局容器(子控件按序排列)""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Pack_new(x, y, w, h, label) @t.NoVTable class Fl_Tile(Fl_Group): """FLTK 可拖动分隔容器""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Tile_new(x, y, w, h, label) @t.NoVTable class Fl_Flex(Fl_Group): """FLTK 弹性布局容器""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Flex_new(x, y, w, h, label) # ============================================================ # Fl_Menu_Button — 弹出菜单按钮 # ============================================================ @t.NoVTable class Fl_Menu_Button(Fl_Widget): """FLTK 弹出菜单按钮(右键/长按弹出)""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Menu_Button_new(x, y, w, h, label) def add_choice(self, text: str) -> int: return Fl_Menu_Button_add_choice(self._ptr, text) # ============================================================ # Fl_Browser — 列表浏览 # ============================================================ @t.NoVTable class Fl_Browser(Fl_Widget): """FLTK 列表浏览框""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Browser_new(x, y, w, h, label) def value(self) -> int: """当前选中行号(1 起;0=未选中)""" return Fl_Browser_value(self._ptr) def add(self, newtext: str): Fl_Browser_add(self._ptr, newtext) def clear(self): Fl_Browser_clear(self._ptr) def text(self, line: int) -> str: return Fl_Browser_text(self._ptr, line) # ============================================================ # Fl_Tree — 树形控件 # ============================================================ @t.NoVTable class Fl_Tree(Fl_Widget): """FLTK 树形控件""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Tree_new(x, y, w, h, label) def add(self, name: str) -> Fl_Tree_ItemPtr: """添加节点('a/b/c' 路径自动建父子层级)""" return Fl_Tree_add(self._ptr, name) def clear(self): Fl_Tree_clear(self._ptr) # ============================================================ # Fl_Text_Editor / Fl_Terminal # ============================================================ @t.NoVTable class Fl_Text_Editor(Fl_Text_Display): """FLTK 文本编辑器""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Text_Editor_new(x, y, w, h, label) def insert(self, text: str): """在光标处插入文本""" Fl_Text_Editor_insert(self._ptr, text) def overstrike(self, text: str): """在光标处覆盖插入文本""" Fl_Text_Editor_overstrike(self._ptr, text) @t.NoVTable class Fl_Terminal(Fl_Widget): """FLTK 终端模拟控件(ANSI 转义支持)""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Terminal_new(x, y, w, h, label) def append(self, txt: str): Fl_Terminal_append(self._ptr, txt) # ============================================================ # Fl_File_Chooser — 文件选择对话框 # ============================================================ @t.NoVTable class Fl_File_Chooser: """FLTK 文件选择对话框(cfltk 封装,非原生) new(directory, pattern, type, title);type 用 Fl_File_Chooser_* 常量 (见 _enums.vp:SINGLE/MULTI/DIRECTORY/CREATE/SAVE 等)。""" _ptr: Fl_File_ChooserPtr def __init__(self, d: str, p: str, t: int, title: str): self._ptr = Fl_File_Chooser_new(d, p, t, title) def set_callback(self, cb: bytes, data: bytes = 0): Fl_File_Chooser_set_callback(self._ptr, cb, data) def count(self) -> int: return Fl_File_Chooser_count(self._ptr) def set_directory(self, d: str): Fl_File_Chooser_set_directory(self._ptr, d) def directory(self) -> str: return Fl_File_Chooser_directory(self._ptr) def set_filter(self, p: str): Fl_File_Chooser_set_filter(self._ptr, p) def filter(self) -> str: return Fl_File_Chooser_filter(self._ptr) def filter_value(self) -> int: return Fl_File_Chooser_filter_value(self._ptr) def set_filter_value(self, f: int): Fl_File_Chooser_set_filter_value(self._ptr, f) def set_type(self, t: int): Fl_File_Chooser_set_type(self._ptr, t) def set_label(self, l: str): Fl_File_Chooser_set_label(self._ptr, l) def set_ok_label(self, l: str): Fl_File_Chooser_set_ok_label(self._ptr, l) def show(self): Fl_File_Chooser_show(self._ptr) def shown(self) -> int: return Fl_File_Chooser_shown(self._ptr) def hide(self): Fl_File_Chooser_hide(self._ptr) def value(self, f: int) -> str: """选中的第 f 个文件名(0 起;多选时用 count 遍历)""" return Fl_File_Chooser_value(self._ptr, f) def delete(self): Fl_File_Chooser_delete(self._ptr) # ============================================================ # Fl_Help_Dialog — HTML 帮助对话框 # ============================================================ @t.NoVTable class Fl_Help_Dialog: """FLTK HTML 帮助对话框""" _ptr: Fl_Help_DialogPtr def __init__(self): self._ptr = Fl_Help_Dialog_new() def load(self, f: str) -> int: """加载 HTML 文件""" return Fl_Help_Dialog_load(self._ptr, f) def set_value(self, f: str): """直接设置 HTML 内容""" Fl_Help_Dialog_set_value(self._ptr, f) def value(self) -> str: return Fl_Help_Dialog_value(self._ptr) def show(self): Fl_Help_Dialog_show(self._ptr) def set_text_size(self, s: int): Fl_Help_Dialog_set_text_size(self._ptr, s) def hide(self): Fl_Help_Dialog_hide(self._ptr) def visible(self) -> int: return Fl_Help_Dialog_visible(self._ptr) def delete(self): Fl_Help_Dialog_delete(self._ptr) # ============================================================ # Fl_Input_Choice — 输入+下拉组合 # ============================================================ @t.NoVTable class Fl_Input_Choice(Fl_Group): """FLTK 文本输入 + 下拉选择组合控件""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Input_Choice_new(x, y, w, h, label) def add(self, s: str): Fl_Input_Choice_add(self._ptr, s) def value(self) -> str: """当前输入框文本""" return Fl_Input_Choice_value(self._ptr) # ============================================================ # Fl_Color_Chooser — 颜色选择 # ============================================================ @t.NoVTable class Fl_Color_Chooser(Fl_Group): """FLTK 颜色选择器""" def __init__(self, x: int, y: int, w: int, h: int, label: str = ""): self._ptr = Fl_Color_Chooser_new(x, y, w, h, label) def set_rgb(self, r: t.CDouble, g: t.CDouble, b: t.CDouble) -> int: """设置 RGB 值(0.0~1.0),返回 1=值变更""" return Fl_Color_Chooser_set_rgb(self._ptr, r, g, b) def show(self): Fl_Color_Chooser_show(self._ptr) # ============================================================ # 图片类 # ============================================================ @t.NoVTable class Fl_PNG_Image: """FLTK PNG 图片(从文件加载)""" _ptr: Fl_PNG_ImagePtr def __init__(self, filename: str): self._ptr = Fl_PNG_Image_new(filename) @t.NoVTable class Fl_JPEG_Image: """FLTK JPEG 图片""" _ptr: Fl_JPEG_ImagePtr def __init__(self, filename: str): self._ptr = Fl_JPEG_Image_new(filename) @t.NoVTable class Fl_GIF_Image: """FLTK GIF 图片""" _ptr: Fl_GIF_ImagePtr def __init__(self, filename: str): self._ptr = Fl_GIF_Image_new(filename)