Desenho customizado (onPaint)
Quando nenhum widget serve, crie um Component e sobrescreva onPaint(Paint paint). As
coordenadas são locais (0,0 = canto superior esquerdo; width/height são o tamanho do
componente).
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*; // Paint, GRect, Font
import dev.crossfly.ui.style.*; // Styles
/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
/** Componente custom: desenha um "badge" (pílula colorida com um número). */
static class Badge extends Component
{
private int valor;
Badge(int valor) { this.valor = valor; }
@Override
public void onPaint(Paint paint) throws Exception
{
// Coordenadas LOCAIS: (0,0) = topo-esquerda; width/height = tamanho do componente.
GRect r = new GRect()
.bounds(0, 0, width, height)
.fill(0xFFE53935) // vermelho ARGB
.radius(height / 2); // pílula / círculo
paint.rect(r);
Font f = Styles.font;
String s = String.valueOf(valor);
int tx = (width - (int) f.width(s)) / 2;
int ty = (height - f.scaledHeight()) / 2;
paint.text(s, tx, ty, 0xFFFFFFFF, f); // texto branco centralizado
}
}
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
Badge badge = new Badge(7);
add(LAY_AUTO, badge); // adiciona o componente custom à tela
}
}
Os trechos abaixo mostram só o miolo (o que vai dentro de
onShow()). Para rodar, coloque-os no esqueletoMainWindowacima.
Esqueleto
public class Badge extends Component {
private int valor;
public Badge(int valor) { this.valor = valor; }
@Override public void onPaint(Paint paint) throws Exception {
// fundo redondo preenchido
GRect r = new GRect()
.bounds(0, 0, width, height)
.fill(0xFFE53935) // vermelho
.radius(height / 2); // pílula/círculo
paint.rect(r);
// texto centralizado
Font f = Styles.font;
String s = String.valueOf(valor);
int tx = (width - (int) f.width(s)) / 2;
int ty = (height - f.scaledHeight()) / 2;
paint.text(s, tx, ty, 0xFFFFFFFF, f);
}
}
// para redesenhar após mudar 'valor': repaint();
Primitivas do Paint
| Chamada | Desenha |
|---|---|
paint.rect(GRect r) |
retângulo (preenchido/borda/cantos/sombra) — configure o GRect |
paint.text(String, x, y, color, Font) |
texto |
paint.line(x1, y1, x2, y2, color, thick) |
linha |
paint.image(Image, x, y[, w, h]) |
imagem |
paint.polyline(GLines) / paint.polygon(GLines) |
polilinha / polígono |
GRect — o retângulo configurável
Fluent: .bounds(x,y,w,h) · .fill(color) · .border(color, thick) · .radius(r) /
.radius(tl,tr,br,bl). Depois paint.rect(gr).
GRect card = new GRect().bounds(0, 0, width, height)
.fill(0xFFFFFFFF).border(0xFFE0E0E0, 1).radius(8);
paint.rect(card);
Boas práticas
- Desenhe relativo a
width/height(não valores fixos) — mantém responsivo. - Reaproveite objetos
GRect/Font(campos) em vez de alocar por frame. - Chame
repaint()quando o estado que afeta o desenho mudar (render é sob demanda).
Erros comuns
- Usar coordenadas absolutas de tela no
onPaint— elas são locais ao componente. - Esquecer
repaint()após mudar o dado desenhado. - Passar cor como objeto — cores são
intARGB (a classeColornão existe).
Veja também
- Imagens · Whiteboard · Cores
Esta página foi útil?Obrigado pelo feedback!