本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。
一切都是 Component
这是让框架其余部分“豁然开朗”的核心理念。在 CrossFly 中,不存在“widget”与“container”
两套层级。只有一个基类型 —— Component —— 而任何 Component 一旦获得一个 Layout,
就在那一刻变成了容器。
container = Component + Layout
Component painel = new Component(); // 一个「空」的 Component
painel.setLayout(new VerticalLayout()); // 现在它组织子项 → 是一个容器
painel.add(LAY_AUTO, new Label("Título"));
painel.add(LAY_FILL, new ListView<>(...));
Button 是一个 Component。Label 是一个 Component。Window(屏幕)是一个全屏的
Component。不存在特殊的 Container 类 —— “容纳能力”就只是拥有一个 Layout。
这意味着你始终用同样的方式组合界面,从一个按钮到整个应用皆是如此。
为什么基类要这样设计
Component 必须能扩展到成千上万个实例而不撑爆内存。两个关键决策:
- 用位域(
cbits)代替几十个boolean。 诸如 enabled、visible、focused、 pressed、是否有布局、是否有聚焦样式…… 这些状态是同一个 long 整数中的若干位,而非独立字段。 成千上万个组件 × 几十个布尔标志将造成巨大浪费;一个位域用单个字段就解决了问题。 - _惰性_属性映射(
property(k, v))。 可选的东西(回调、自定义皮肤、背景 图、备用样式)不是固定字段 —— 它们存在于一个按需创建的映射中。一个简单的Label不必为一个永远不会用到的“背景图”字段付出代价。
// property(...) 是表示可选值的惯用「数据袋」:
comp.property("meuFlag", true);
boolean f = comp.property("meuFlag"); // 取回(从未设置则为 null)
样式遵循同样的理念:它们是按需从 Skin 创建的,而非在一开始就为每个组件
实例化。
单一父级层级
每个 Component 最多有一个父级。组合树是严格分层的:将
一个组件添加到某个容器会把它从任何先前的父级中移除。这让布局和事件
传播保持可预测(每个组件恰好属于一个位置)。
由此推导出的结论
- 组合一切的方式只有一种: 学会搭建一个面板 = 学会搭建一个屏幕。
- 布局是可插拔的: 同一个容器只需更换
Layout就能改变排布方式(这是 响应式的基础 —— 参见 Layout 与 Relative 模型)。 - 每个组件成本低: 位域 + 惰性属性正是让大型列表可行的原因。
参见
这个页面有帮助吗?感谢你的反馈!