Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar
Todos os exemplos
ReceitasAvisos131 linhas · 1 arquivos

Waiting

Known length gets a bar. Unknown gets a spinner. A finished measurement — a share, a score — gets a ring, and that one is not waiting at all.

O que isto mostra

Making the user wait, in the three shapes waiting actually comes in.

The choice is not decoration: it is whether you know how long. A spinner over a job whose length you know throws away the only reassurance the user wants; a percentage over a job whose length you are guessing is a lie they will catch at 99%.

Rodar na sua máquina

Todo exemplo é uma Window comum, então o launcher só precisa do nome dela.

gradlew lwjgl3:run --args="classname dev.cf.recipe.R13Waiting"
Editar o exemplo

Java é compilado antes de rodar, então o navegador não consegue reconstruir uma edição sozinho — o código que você vê aqui virou JavaScript pelo TeaVM antes de ser publicado. Copie o arquivo para um projeto e ele roda sem mudanças nas quatro plataformas; o comando acima é toda a preparação.

Rodando aquiCrossFly 0.1.32
Iniciando o aplicativo…

Compilado para JavaScript pelo TeaVM — é o mesmo código, não um vídeo dele. · Todos os exemplos

O que ele usa

Tipos do framework que este exemplo toca. Os que têm link têm página de referência.

ButtonComponentMainPalColorPlatformUtilsProgressRadialProgressRelativeScreenSkinStylesWidgets

O código

Completo, sem cortes. É o arquivo, não um trecho dele.

Bruto
dev/cf/recipe/R13Waiting.java
package dev.cf.recipe;

import dev.cf.Tones;

import dev.crossfly.Main;
import dev.crossfly.PlatformUtils;
import dev.crossfly.ui.*;
import dev.crossfly.ui.color.*;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.skin.Skin;
import dev.crossfly.ui.style.*;

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

/**
 * Making the user wait, in the three shapes waiting actually comes in.
 *
 * <p>The choice is not decoration: it is whether you know how long. A spinner over a job whose
 * length you know throws away the only reassurance the user wants; a percentage over a job whose
 * length you are guessing is a lie they will catch at 99%.</p>
 */
public class R13Waiting extends Recipe
{
   private Progress bar;
   private RadialProgress ring;
   private boolean running;

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

   public String note()
   {
      return "Known length gets a bar. Unknown gets a spinner. A finished measurement — a share, a"
         + " score — gets a ring, and that one is not waiting at all.";
   }

   public void build(Component body) throws Exception
   {
      head(body, 0xE88B, "Unknown length", Tones.support());
      Progress spin = new Progress(Styles.progressType());
      spin.style(Skin.get()
         .progress()
         .autoWidth(Relative.ofFont(12f)));
      body.add(LAY_AUTO, outgap(spin, 0, 0, 0, 1.2f));

      head(body, 0xE9E4, "Known length", Tones.accent());
      bar = new Progress(0f, 1f);
      bar.style(Skin.get()
         .progress()
         .autoWidth(Relative.ofFont(16f)));
      body.add(LAY_AUTO, outgap(bar, 0, 0, 0, .5f));
      Button go = Tones.action("Run it");
      go.onAction(c -> run());
      body.add(LAY_AUTO, outgap(go, 0, 0, 0, 1.2f));

      head(body, 0xE6C4, "Not waiting — a measurement", Tones.highlight());
      ring = new RadialProgress().progress(.41f)
         .text("41%")
         .caption("converted");
      body.add(LAY_AUTO, ring);
   }

   /**
    * The work runs off the paint thread and reports back through it.
    *
    * <p>Advancing the bar from the paint thread means the bar cannot advance: the thread that would
    * draw it is the thread doing the work. This is the single most common reason a progress bar
    * jumps from 0 to 100 with nothing in between.</p>
    *
    * <p><b>And "off the paint thread" has two shapes, because one platform has one thread.</b>
    * {@link PlatformUtils#hasThreads()} is false in the browser: there the work is cut into slices
    * and each slice runs from a timer, so the page paints between them. Asking the question instead
    * of assuming a thread is what makes this recipe correct on all five &mdash; until 28/09/2026 it
    * started a {@code Thread} unconditionally, which is exactly the code a reader would copy.</p>
    */
   private void run()
   {
      if (running)
         return;
      running = true;
      if (!PlatformUtils.instance.hasThreads())
      {
         final int[] step = {0};
         final com.badlogic.gdx.utils.Timer.Task[] task = new com.badlogic.gdx.utils.Timer.Task[1];
         task[0] = addTimer(() ->
         {
            // One slice of work per tick: this runs ON the paint thread, so it must be short.
            bar.setValue(++step[0] / 20f);
            Screen.repaint();
            if (step[0] >= 20)
            {
               removeTimer(task[0]);
               running = false;
            }
         }, .09f);
         return;
      }
      new Thread(() ->
      {
         for (int i = 1; i <= 20; i++)
         {
            final float f = i / 20f;
            Main.runOnPaintThread(() ->
            {
               bar.setValue(f);
               Screen.repaint();
            });
            try
            {
               Thread.sleep(90);
            }
            catch (InterruptedException e)
            {
               Thread.currentThread()
                  .interrupt();
               break;
            }
         }
         running = false;
      }, "recipe-progress").start();
   }

   private void head(Component body, int icone, String t, PalColor tom) throws Exception
   {
      body.add(LAY_AUTO, Tones.head(icone, t, tom));
   }
}
Para uma IA

Versões desta página legíveis por máquina, para um modelo ler a prateleira em vez de adivinhar a API.

Este exemplo, em JSONEste exemplo, em Markdown
AnteriorBottom nav that becomes a railPróximoCards that reflow