布局 Layouts
FLTK-rs提供了这些开箱即用的布局组件:
- Flex
- Pack
- Grid
- 组件相对定位
Flex
Flex
组件可以让你灵活的布局。它在group mod
中定义,实现了GroupExt Trait
。可以使用set_type
或with_type
方法选择Flex的布局形式。比如列(Column)和行(Row)布局:
use fltk::{prelude::*, *}; fn main() { let a = app::App::default().with_scheme(app::Scheme::Gtk); let mut win = window::Window::default().with_size(400, 300); let mut flex = group::Flex::new(0, 0, 400, 300, None); flex.set_type(group::FlexType::Column); let expanding = button::Button::default().with_label("Expanding"); let normal = button::Button::default().with_label("Normal"); flex.fixed(&normal, 30); flex.end(); win.end(); win.show(); a.run().unwrap(); }
fixed
方法 (在1.4.6版本前是 set_size
)方法 接收一个放在Flex内部的组件,将其大小(高度或宽度)设置为传递的值,示例中设置高度为30。因为这是一个Column类型的Flex,所以传入的值代表组件的高度。
示例中另一个按钮大小是变的,因为没有为它设置尺寸。参见这个完整的例子:
Packs
Pack
组件同样在group mod
中,并实现了GroupExt trait
。类似的,也有两种形式的Pack,Vertical Pack
和 Horizontal Pack
,Pack默认是Vertical,它需要设置子组件的高度,而Horizontal Pack需要设置它的子组件的宽度,比如这个示例:
use fltk::{prelude::*, *}; fn main() { let app = app::App::default(); let mut my_window = window::Window::default().with_size(400, 300); let mut hpack = group::Pack::default().with_size(190, 40).center_of(&my_window); hpack.set_type(group::PackType::Horizontal); hpack.set_spacing(30); let _but1 = button::Button::default().with_size(80, 0).with_label("Button1"); let _but2 = button::Button::default().with_size(80, 0).with_label("Button2"); hpack.end(); my_window.end(); my_window.show(); app.run().unwrap(); }
我们在窗口内创建了一个Pack
,并在其中创建2个按钮。我们不需要设置按钮的坐标。你也可以像 FLTK仓库的示例 中的Calculator
一样,将Pack互相嵌套。可以试试Pack::auto_layout()
方法自动布局:
use fltk::{prelude::*, *}; fn main() { let app = app::App::default(); let mut my_window = window::Window::default().with_size(400, 300); let mut hpack = group::Pack::new(0, 200, 400, 100, ""); hpack.set_type(group::PackType::Horizontal); hpack.set_spacing(30); let _but1 = button::Button::default().with_label("Button1"); let _but2 = button::Button::default().with_label("Button2"); hpack.end(); hpack.auto_layout(); my_window.end(); my_window.show(); app.run().unwrap(); }
这种情况下,我们甚至不需要设置按钮的大小。
Grid
Grid Crate实现在另一个Crate中的。它需要使用Grid::set_layout(&mut self, rows, columns)
来设置一个Layout。然后通过Grid::insert(&mut self, row, column)
或Grid::insert_ext(&mut self, row, column, row_span, column_span)
方法添加组件。
use fltk::{prelude::*, *}; use fltk_grid::Grid; fn main() { let a = app::App::default().with_scheme(app::Scheme::Gtk); let mut win = window::Window::default().with_size(500, 300); let mut grid = Grid::default_fill(); // 若为 "true" 便会显示网格的框线和数字 grid.debug(false); // 设置Grid为 5 行,5 列 grid.set_layout(5, 5); // 设置组件和所在的行列 grid.insert(&mut button::Button::default().with_label("Click"), 0, 1); // 设置组件和所在的行列以及行高列宽 grid.insert_ext(&mut button::Button::default().with_label("Button 2"), 2, 1, 3, 1); win.end(); win.show(); a.run().unwrap(); }
Relative positioning
WidgetExt Trait
中定义了几个构造方法,允许我们相基于其他组件的大小和位置构建组件。这类似于Qt中Qml的锚定(anchoring):
use fltk::{prelude::*, *}; fn main() { let app = app::App::default(); let mut wind = window::Window::default() .with_size(160, 200) .center_screen() .with_label("Counter"); let mut frame = frame::Frame::default() .with_size(100, 40) .center_of(&wind) .with_label("0"); let mut but_inc = button::Button::default() .size_of(&frame) .above_of(&frame, 0) .with_label("+"); let mut but_dec = button::Button::default() .size_of(&frame) .below_of(&frame, 0) .with_label("-"); wind.end(); wind.show(); app.run().unwrap(); }
(我们跳过了一些主题的设计)
这些方法是:
above_of(&widget, padding)
: 将该组件放在所传递的组件上面below_of(&widget, padding)
: 将该组件放在所传递的组件下面right_of(&widget, padding)
: 将该组件放在所传递的组件右边left_of(&widget, padding)
:将该组件置于所传递的组件左边center_of(&widget)
: 将组件放置在所传递的组件的中间(包括x和y轴)center_of_parent()
: 将组件放在父组件的中间(包括x轴和y轴)center_x(&widget)
: 将组件放置在所传递的组件的中心(X轴)center_y(&widget)
: 将组件放置在所传递的组件的中心(Y轴)size_of(&widget)
: 构建与所传组件相同大小的组件size_of_parent()
: 构建与其父组件相同大小的组件