跳到内容
CrossFly 是 100% 开源在 GitHub 关注我们
CrossFlyCrossFly
开始使用

本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。

Picker(基类)

Picker 是 CrossFly 所有选择窗口(日期、时间、文件、照片、颜色、条形码、坐标)的通用基类。每个 picker 打开后,让用户进行交互,并在确认时自行关闭,通过回调将结果异步地交付给打开它的代码。

理解本页的模式,就等于一次性理解了所有 picker。

🟡 · 包: dev.crossfly.ui.picker · 继承: Window · 过渡: 默认 FADE

核心模式:getAnswer() + show(onAnswer)

  • Picker.getAnswer() 产生所选的值(每个子类都会重写它以返回具体类型:String、Integer、LatLon……)。在基类中返回 null。
  • Window.show(RunnableWith<Object> onAnswer) 在窗口关闭时消费这个值。

两者之间的纽带位于 Window.hide():

public void hide() {
   ...
   Object answer = this instanceof Picker ? ((Picker) this).getAnswer() : null;
   if (onAnswer != null && answer != null)
      onAnswer.run(answer);
   ...
}

实际后果(均已在代码中确认):

  • 回调 onAnswer 仅在 hide() 时触发,且仅当 getAnswer() != null 时。 在取消时,子类会让 getAnswer() 返回 null —— 因此 onAnswer 不会被调用。需要对取消作出反应的代码应重写 onHide()/onRemove() 或使用子类特定的回调。
  • show(onAnswer) 是线程安全的:如果在 paint 线程之外调用,它会被重新调度并阻塞直到完成。
  • 交付的值是 Object;消费者需将其强制转换为该 picker 的具体类型。

这与 Alert/ActionSheet 形成对比,它们继承自 Window 但不继承 Picker —— 在它们中 show(onAnswer) 不会触发,响应通过按钮回调返回。

完整示例(复制、粘贴并运行)

package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.picker.*;

/** 可执行的主界面。将 launcher 指向此类(classname)并运行:gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Button abrir = new Button("Abrir picker");
      abrir.onAction(c ->
      {
         // 任何 Picker 的子类都遵循相同的 show(onAnswer) 模式
         DatePicker dp = new DatePicker();
         dp.show(answer ->
         {
            // 'answer' 是 getAnswer() 返回的 Object;只有在 != null 时才会到达这里
            String data = (String) answer;
            Hint.show("Selecionado: " + data, 2000);
         });
      });
      add(LAY_AUTO, abrir);
   }
}

下面的片段只展示核心部分(放入 onShow() 内的内容)。要运行它们,请将它们放入上面的 MainWindow 骨架中。

基本用法(任何 picker 的通用形式)

DatePicker dp = new DatePicker();
dp.show(answer ->
{
   // 'answer' 是 getAnswer() 返回的 Object;只有在 != null 时才会到达这里
   String data = (String) answer;
   Debug.log("Selecionado: " + data);
});

公共方法

方法 返回 描述
getAnswer() Object picker 的结果,若取消则为 null。由每个子类重写。
show(RunnableWith<Object> onAnswer) void 打开 picker;关闭时通过回调交付值(继承自 Window)。

各子类返回的类型

Picker getAnswer() 返回
DatePicker String(日期,遵循 LocaleFormats.dateFormat/dateSeparator)
TimePicker String(HH:MM,24 小时制)
FilePicker —(空骨架;从基类继承 null)
PhotoPicker String(路径或 "ERROR: ...")
ColorPicker Integer(不含 alpha 的 RGB)
BarcodePicker String(读取的载荷)
LocationPicker LatLon

最佳实践

  • 始终将 Object 强制转换为上表中的具体类型。
  • 要对取消作出反应,不要依赖 onAnswer —— 使用特定回调(onSelect/onCapture)或重写 onHide()。
  • 硬件 picker(PhotoPicker、BarcodePicker、LocationPicker)在关闭时释放资源;不要在 hide() 之后重用同一个实例。

常见错误

  • 在取消时期待 onAnswer —— 它不会触发,因为 getAnswer() 返回 null。
  • 忘记强制转换 —— 回调接收的是 Object。

另见

这个页面有帮助吗?