221 条记录
22 私有链接
22 私有链接
下面这份“小抄”按常见需求→该用哪个容器来选,外加要点/坑位提醒(Rust fltk
名称在括号里):
选哪个?
需求 | 首选容器 | 为什么 | 关键要点 / 易踩点 |
---|---|---|---|
普通窗口 | Fl_Window (window::Window) | 基本窗口 | 需要防闪烁/重绘多→用 Fl_Double_Window |
重绘频繁、动画、自绘画布 | Fl_Double_Window (WindowType::Double 或 window::DoubleWindow) | 双缓冲,减少闪烁 | 会多占一块离屏缓冲(内存↑) |
OpenGL 内容 | Fl_Gl_Window (window::GlWindow) | 独立 GL 上下文 | 在 draw 里做 GL 绘制;注意与 UI 线程/重绘时机 |
内容需要滚动 | Fl_Scroll (group::Scroll) | 提供滚动条 | 通常在 Scroll 里再放一个内部 Group 承载内容;大内容要 resizable |
页签切换 | Fl_Tabs (group::Tabs) | 多页签 | 每个 Tab 是一个子 Group;调整 resizable 让内容随窗缩放 |
向导/一步一步 | Fl_Wizard (group::Wizard) | 同时只显示一个页面 | 用 next()/prev() 切换;每页是一个子 Group |
左右/上下线性自适应布局 | Fl_Flex (group::Flex) | 现代化线性布局(行/列),支持权重 | 用 flex.set_size(&child, px) 固定某子项尺寸;其余自动分配 |
栅格(表单/面板) | Fl_Grid (group::Grid) | 行×列网格,自动布局 | 适合复杂对齐;比 Pack 更可控;避免与其它“自伸缩容器”深度嵌套 |
简单“依次排队” | Fl_Pack (group::Pack) | 顺序排列(横/竖) | 轻量但不如 Flex/Grid 灵活;不建议做复杂自适应 |
可拖拽分隔的“分栏” | Fl_Tile (group::Tile) | 平铺区块,可拖动边界 | 类似“分割面板”;子项自己绘制边界/把手感稍原始 |
只是把一批控件当作整体管理/隐藏/禁用 | Fl_Group (group::Group) | 基类容器,纯“打包” | 用来分组、统一 deactivate()/hide()、抓事件;坐标仍靠你手摆 |
实战建议(精简版)
- 新项目优先:
Flex
(线性)/Grid
(表格) 做主布局,里面再放普通Group
+控件。 - 滚动内容:
Scroll -> Group -> 内容
三级结构更稳;给内部 group 做resizable
。 - 分隔面板:
Tile
;如果只是简单两栏,也可“Flex + 固定一侧尺寸”。 - 重绘多:窗口设
WindowType::Double
,自绘控件也尽量在双缓冲里。 - 避免把多个“自伸缩容器”(
Flex / Grid / Pack / Tile
)层层套娃;层次深了容易出现尺寸争用或奇怪的重排。 - 缩放跟随:为顶层窗口
window.resizable(&some_child)
指定“跟随缩放”的基准控件(常是主内容区)。 - Tabs/Wizard:每页用子
Group
;只让每页的主内容resizable
,避免整个页上所有控件乱拉伸。
迷你模板(Rust)
Flex(列布局):
use fltk::{prelude::*, group::Flex, enums::Align};
let mut flex = Flex::default_fill().column(); // 占满父容器,竖向排
flex.set_margin(8);
flex.set_pad(8);
// ... add children here ...
// flex.set_size(&child_fixed, 120); // 固定某子项高度(列布局时=高度)
flex.end();
Scroll with inner group:
use fltk::{prelude::*, group::{Scroll, Group}};
let mut scroll = Scroll::default_fill();
let mut inner = Group::default().with_size(800, 1200); // 内容实际大小
// ... 放很多子控件 ...
inner.end();
scroll.end();
// 让滚动区域以 inner 为基准自适应
scroll.set_scrollbar_size(14);
双缓冲窗口:
use fltk::{prelude::*, window::Window, enums::WindowType};
let mut win = Window::new(100, 100, 900, 600, None);
win.set_type(WindowType::Double);
// win.resizable(&main_area);
win.end();
win.show();