Whiteboard
Whiteboard é uma superfície de desenho livre: o usuário arrasta o dedo/ponteiro e o componente registra os pontos, suaviza o traço (média ponderada dos vizinhos) e o renderiza sobre uma Image interna. É a base para captura de assinatura, anotações à mão e pequenos rascunhos. Cada traço concluído (no onTouchUp) é “queimado” na imagem, de modo que o histórico acumula sem reprocessar todos os pontos a cada quadro.
Você controla a cor da caneta (setPenColor), a espessura (campo thick) e pode limpar (clear()) ou exportar/definir a imagem de fundo (getImage/setImage).
🟢 · Pacote:
dev.crossfly.ui· Estende:Component· Estilo:ComponentStyle(fundo branco por default)
Quando usar
- Capturar uma assinatura ou um desenho à mão livre.
- Anotar sobre uma imagem existente (passe-a via
setImage).
Quando NÃO usar
- Exibir/plotar dados estruturados → use
chartview.
Aparência
Fundo branco (backColor) do tamanho do componente. Os traços são linhas suavizadas com espessura Styles.fontHeight/3 (grosso) ou Styles.fontHeight/10 (fino), na cor da caneta (com alpha forçado para opaco). O componente tem hasPan(true), ou seja, captura o gesto de arrastar para desenhar.
Exemplo completo (copiar, colar e rodar)
Whiteboard é um componente comum: entra direto na tela com add(LAY_FILL, ...) para ocupar o corpo. O exemplo reutiliza o uso básico (caneta azul, traço grosso) e adiciona um botão para limpar.
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** Tela principal executável. Aponte o launcher (classname) e rode: 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); // azul (o alpha é forçado para opaco no desenho)
board.thick = true; // traço grosso
Button limpar = new Button("Limpar")
.onAction(c -> board.clear());
add(LAY_AUTO, limpar);
add(LAY_FILL, board); // ocupa o corpo da tela
}
}
Os trechos abaixo mostram só o miolo (o que vai dentro de
onShow()). Para rodar, coloque-os no esqueletoMainWindowacima.
Uso básico
Whiteboard board = new Whiteboard();
board.setPenColor(0x0000FF); // azul (o alpha é forçado para opaco no desenho)
board.thick = true; // traço grosso
container.add(LAY_FILL, board);
// Em outro lugar, um botão para limpar:
btnLimpar.onAction(c -> board.clear());
Construtores
| Construtor | Descrição |
|---|---|
Whiteboard() |
Cria a superfície com fundo branco e hasPan(true) (pronta para desenho). |
Propriedades e personalização
| Propriedade / método | Tipo | Padrão | O que faz |
|---|---|---|---|
setPenColor(int) |
void |
BLACK |
Define a cor da caneta (o desenho força alpha opaco). |
getPenColor() |
int |
— | Retorna a cor atual da caneta. |
thick |
boolean (campo) |
false |
true = traço grosso (fontHeight/3); false = fino (fontHeight/10). |
clear() |
void |
— | Limpa a imagem e os pontos acumulados. |
getImage() |
Image |
null |
Retorna a imagem de desenho (pode ser null se nada foi desenhado). |
setImage(Image) |
void |
— | Define a imagem de fundo/base (passe null para superfície vazia). throws ImageException. |
Whiteboard.debugPoints |
boolean estático |
false |
Depuração: exibe contagem de pontos/tempo de renderização. |
Callbacks e eventos
Whiteboard trata os gestos internamente; não expõe um callback de “traço concluído”.
| Evento (interno) | Comportamento |
|---|---|
onTouchDown(x,y,button) |
Inicia um novo traço e grava o primeiro ponto. |
onPan(x,y,dx,dy) |
Acumula pontos enquanto o usuário arrasta e repinta. |
onTouchUp(x,y,button) |
Finaliza o traço e “queima” o desenho na Image interna. |
Estados
- desenhando: entre
onTouchDowneonTouchUp, os pontos ficam em um buffer temporário e são suavizados/renderizados a cadaonPan. - consolidado: no
onTouchUp, o traço é gravado naImagee o buffer é limpo (o custo por quadro não cresce com o total de traços).
Painel de assinatura com seleção de cor e exportação
Whiteboard assinatura = new Whiteboard();
assinatura.thick = false; // traço fino para assinar
container.add(LAY_FILL, assinatura);
btnPreto.onAction(c -> assinatura.setPenColor(0x000000));
btnAzul.onAction (c -> assinatura.setPenColor(0x0000FF));
btnLimpar.onAction(c -> assinatura.clear());
// Ao confirmar, recupere a imagem resultante:
btnOk.onAction(c -> {
Image desenho = assinatura.getImage(); // pode ser null se nada foi desenhado
if (desenho != null)
salvarAssinatura(desenho);
});
Boas práticas
- Prefira
thick = falsepara assinaturas (traço mais preciso) ethick = truepara rascunhos amplos. - Sempre verifique
getImage() != nullantes de exportar: se o usuário não desenhou nada, a imagem ainda énull. - Ofereça um botão de
clear()— não há “desfazer” por traço.
Erros comuns
- Passar uma cor com alpha explícito esperando transparência: o desenho força alpha opaco (
0xFF000000 | cor). - Esperar um callback de traço: use os métodos (
getImage) após a interação; não háonActionde conclusão de traço.