跳到内容
CrossFly 是 100% 开源在 GitHub 关注我们
CrossFlyCrossFly
开始使用

本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。

自定义绘制(onPaint)

当没有任何 widget 合适时,创建一个 Component 并重写 onPaint(Paint paint)。坐标是 局部的(0,0 = 左上角;width/height 是组件的尺寸)。

完整示例(复制、粘贴并运行)

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

/** 可执行的主界面。将 launcher 指向此类(classname)并运行:gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   /** 自定义组件:绘制一个"徽章"(带数字的彩色药丸)。 */
   static class Badge extends Component
   {
      private int valor;

      Badge(int valor) { this.valor = valor; }

      @Override
      public void onPaint(Paint paint) throws Exception
      {
         // 本地坐标:(0,0) = 左上角;width/height = 组件尺寸。
         GRect r = new GRect()
            .bounds(0, 0, width, height)
            .fill(0xFFE53935)          // 红色 ARGB
            .radius(height / 2);       // 药丸 / 圆形
         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);   // 居中的白色文本
      }
   }

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());
      Badge badge = new Badge(7);
      add(LAY_AUTO, badge);   // 将自定义组件添加到屏幕
   }
}

下面的片段只展示了核心部分(放入 onShow() 内部的内容)。要运行它们,请将其放入上面的 MainWindow 骨架中。

骨架

public class Badge extends Component {
   private int valor;
   public Badge(int valor) { this.valor = valor; }

   @Override public void onPaint(Paint paint) throws Exception {
      // 填充的圆形背景
      GRect r = new GRect()
         .bounds(0, 0, width, height)
         .fill(0xFFE53935)               // 红色
         .radius(height / 2);            // 药丸形/圆形
      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);
   }
}
// 修改“值”后重绘:repaint();

Paint 的绘图原语

调用 绘制
paint.rect(GRect r) 矩形(填充/边框/圆角/阴影)— 配置 GRect
paint.text(String, x, y, color, Font) 文本
paint.line(x1, y1, x2, y2, color, thick) 线条
paint.image(Image, x, y[, w, h]) 图像
paint.polyline(GLines) / paint.polygon(GLines) 折线 / 多边形

GRect — 可配置的矩形

流式:.bounds(x,y,w,h) · .fill(color) · .border(color, thick) · .radius(r) / .radius(tl,tr,br,bl)。然后 paint.rect(gr)。

GRect card = new GRect().bounds(0, 0, width, height)
   .fill(0xFFFFFFFF).border(0xFFE0E0E0, 1).radius(8);
paint.rect(card);

最佳实践

  • 绘制时相对于 width/height(而非固定值)— 保持响应式。
  • 复用 GRect/Font 对象(作为字段),而不是每帧分配。
  • 当影响绘制的状态改变时,调用 repaint()(渲染是按需的)。

常见错误

  • 在 onPaint 中使用屏幕的绝对坐标 — 它们是相对于组件的局部坐标。
  • 改变被绘制的数据后忘记 repaint()。
  • 将颜色作为对象传递 — 颜色是 int ARGB(Color 类不存在)。

另请参阅

这个页面有帮助吗?