跳到内容
CrossFly 是 100% 开源在 GitHub 关注我们
CrossFlyCrossFly
开始使用
全部示例
配方输入84 行 · 1 个文件

Pickers

show(answer -> …) on all of them, and answer is null when the user backed out. The ones needing hardware live in R21, and the system file picker in R31 — those can be refused.

它展示了什么

The pickers, and the callback shape they all share.

Every picker is a Window that answers: show(answer -> …), where answer is null when the user cancelled. One shape for date, time, colour, file, photo, barcode and location — so learning one is learning all of them.

Handle the null. Cancelling is not an error and not an edge case; it is the most common outcome of opening a picker by mistake, and a callback that assumes an answer throws on a path every user takes.

For a date inside a form, do not open a picker by hand at all — a TextField in EditMode.DATE opens it for you and writes the answer back. See R10Form.

在你的机器上运行

每个示例都是普通的 Window,启动器只需要它的名字。

gradlew lwjgl3:run --args="classname dev.cf.recipe.R20Pickers"
修改它

Java 是提前编译的,浏览器无法自行重建你的修改 —— 这里的代码在发布前已由 TeaVM 转成 JavaScript。把文件复制到项目里,它在四个平台上原样运行;上面那条命令就是全部准备工作。

正在此处运行CrossFly 0.1.32
正在启动应用…

由 TeaVM 编译为 JavaScript —— 是同一份代码,不是录像。 · 全部示例

它用到了什么

本示例触及的框架类型。带链接的有参考页。

CardColorPickerComponentDatePickerDateRangePickerGapGridLayoutLabelScreenStylesTimePickerWidgets

源码

完整无删减。这就是那个文件,不是片段。

原始
dev/cf/recipe/R20Pickers.java
package dev.cf.recipe;

import dev.cf.Tones;

import dev.crossfly.ui.*;
import dev.crossfly.ui.color.*;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.picker.*;
import dev.crossfly.ui.style.*;

import static dev.crossfly.ui.Widgets.*;

/**
 * The pickers, and the callback shape they all share.
 *
 * <p>Every picker is a {@link dev.crossfly.ui.Window} that answers:
 * {@code show(answer -> …)}, where {@code answer} is {@code null} when the user cancelled. One
 * shape for date, time, colour, file, photo, barcode and location — so learning one is learning
 * all of them.</p>
 *
 * <p><b>Handle the null.</b> Cancelling is not an error and not an edge case; it is the most common
 * outcome of opening a picker by mistake, and a callback that assumes an answer throws on a path
 * every user takes.</p>
 *
 * <p>For a date <i>inside a form</i>, do not open a picker by hand at all — a {@code TextField} in
 * {@code EditMode.DATE} opens it for you and writes the answer back. See {@link R10Form}.</p>
 */
public class R20Pickers extends Recipe
{
   private Label answer;

   public String title()
   {
      return "Pickers";
   }

   public String note()
   {
      return "show(answer -> …) on all of them, and answer is null when the user backed out. The"
         + " ones needing hardware live in R21, and the system file picker in R31 — those can be"
         + " refused.";
   }

   public void build(Component body) throws Exception
   {
      answer = label("Nothing picked yet.", 1f, false, Styles.captionColor, Position.START);
      answer.testTag("pickers.answer");
      // Pinned below the scrolling body, so the answer stays in view (see Recipe.pin).
      pin(answer);

      open(body, 0xE878, "Date", () -> new DatePicker().show(a -> said("Date", a)));
      open(body, 0xE8B5, "Time", () -> new TimePicker().show(a -> said("Time", a)));
      open(body, 0xE916, "Date range", () -> new DateRangePicker().show(a -> said("Range", a)));
      open(body, 0xE40A, "Colour", () -> new ColorPicker(Styles.primaryColor.color())
         .show(a -> said("Colour", a)));
   }

   /** A row per picker: its glyph on a tonal tile, its name, and the whole card opens it. */
   private void open(Component body, int icone, String name, Runnable go) throws Exception
   {
      Card c = new Card();
      c.setLayout(new GridLayout(Position.START, Position.CENTER));
      c.getStyle()
         .outgap(Gap.ofFont(0, 0, 0, .5f))
         .pressable();
      c.testTag("pickers." + name.toLowerCase()
         .replace(' ', '.'));
      c.onAction(e -> go.run());
      c.add(0f, 1f, 0f, Tones.tile(icone, Tones.accent()),
         outgap(label(name, 1.2f, true, Styles.textColor, Position.START), .6f, 0, 0, 0),
         matglyph(0xE5CC, tertiary(), 1f));   // chevron_right
      body.add(LAY_AUTO, c);
   }

   /** One place that handles the answer, including the null every picker can return. */
   private void said(String what, Object a)
   {
      answer.setText(a == null ? what + ": cancelled" : what + ": " + a);
      answer.invalidateMeasure(); // the pinned band must grow with it (see Recipe.pin)
      Screen.repaint();
   }
}
给 AI 助手

本页的机器可读版本,让模型直接读取示例集,而不是猜测 API。

本示例(JSON)本示例(Markdown)
上一个Capturing a signature下一个Camera, barcode and GPS