Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

Whiteboard

Whiteboard is a freehand drawing surface: the user drags their finger/pointer and the component records the points, smooths the stroke (weighted average of neighbors), and renders it onto an internal Image. It is the foundation for signature capture, handwritten notes, and small sketches. Each completed stroke (on onTouchUp) is “burned” into the image, so that the history accumulates without reprocessing all points on every frame.

You control the pen color (setPenColor), the thickness (the thick field), and you can clear (clear()) or export/set the background image (getImage/setImage).

🟢 · Package: dev.crossfly.ui · Extends: Component · Style: ComponentStyle (white background by default)

When to use

  • Capture a signature or a freehand drawing.
  • Annotate over an existing image (pass it in via setImage).

When NOT to use

  • Display/plot structured data → use chartview.

Appearance

White background (backColor) the size of the component. The strokes are smoothed lines with thickness Styles.fontHeight/3 (thick) or Styles.fontHeight/10 (thin), in the pen color (with alpha forced to opaque). The component has hasPan(true), meaning it captures the drag gesture to draw.

Complete example (copy, paste, and run)

Whiteboard is an ordinary component: it goes straight onto the screen with add(LAY_FILL, ...) to occupy the body. The example reuses the basic usage (blue pen, thick stroke) and adds a button to clear.

package com.exemplo;

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

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Whiteboard board = new Whiteboard();
      board.setPenColor(0x0000FF);   // blue (the alpha is forced to opaque on draw)
      board.thick = true;            // thick stroke

      Button limpar = new Button("Limpar")
         .onAction(c -> board.clear());
      add(LAY_AUTO, limpar);

      add(LAY_FILL, board);          // occupies the body of the screen
   }
}

The snippets below show only the core (what goes inside onShow()). To run them, place them in the MainWindow skeleton above.

Basic usage

Whiteboard board = new Whiteboard();
board.setPenColor(0x0000FF);   // blue (the alpha is forced to opaque on draw)
board.thick = true;            // thick stroke
container.add(LAY_FILL, board);

// Elsewhere, a button to clear:
btnLimpar.onAction(c -> board.clear());

Constructors

Constructor Description
Whiteboard() Creates the surface with a white background and hasPan(true) (ready for drawing).

Properties and customization

Property / method Type Default What it does
setPenColor(int) void BLACK Sets the pen color (drawing forces opaque alpha).
getPenColor() int — Returns the current pen color.
thick boolean (field) false true = thick stroke (fontHeight/3); false = thin (fontHeight/10).
clear() void — Clears the image and the accumulated points.
getImage() Image null Returns the drawing image (may be null if nothing was drawn).
setImage(Image) void — Sets the background/base image (pass null for an empty surface). throws ImageException.
Whiteboard.debugPoints boolean static false Debug: displays point count/render time.

Callbacks and events

Whiteboard handles gestures internally; it does not expose a “stroke completed” callback.

Event (internal) Behavior
onTouchDown(x,y,button) Starts a new stroke and records the first point.
onPan(x,y,dx,dy) Accumulates points while the user drags and repaints.
onTouchUp(x,y,button) Finalizes the stroke and “burns” the drawing into the internal Image.

States

  • drawing: between onTouchDown and onTouchUp, the points stay in a temporary buffer and are smoothed/rendered on each onPan.
  • consolidated: on onTouchUp, the stroke is written into the Image and the buffer is cleared (the per-frame cost does not grow with the total number of strokes).

Signature panel with color selection and export

Whiteboard assinatura = new Whiteboard();
assinatura.thick = false;                 // thin stroke for signing
container.add(LAY_FILL, assinatura);

btnPreto.onAction(c -> assinatura.setPenColor(0x000000));
btnAzul.onAction (c -> assinatura.setPenColor(0x0000FF));
btnLimpar.onAction(c -> assinatura.clear());

// On confirm, retrieve the resulting image:
btnOk.onAction(c -> {
   Image desenho = assinatura.getImage();   // may be null if nothing was drawn
   if (desenho != null)
      salvarAssinatura(desenho);
});

Best practices

  • Prefer thick = false for signatures (more precise stroke) and thick = true for broad sketches.
  • Always check getImage() != null before exporting: if the user drew nothing, the image is still null.
  • Offer a clear() button — there is no per-stroke “undo”.

Common mistakes

  • Passing a color with explicit alpha expecting transparency: drawing forces opaque alpha (0xFF000000 | cor).
  • Expecting a stroke callback: use the methods (getImage) after the interaction; there is no stroke-completion onAction.

See also

Was this page helpful?