BasicButtonUI基本按钮外观

wen java案例 1

本文目录导读:

BasicButtonUI基本按钮外观

  1. 核心职责
  2. 关键方法
  3. 典型使用场景
  4. 与系统外观的集成
  5. 注意事项
  6. 简单示例:完整扁平按钮 UI

在 Java Swing 中,BasicButtonUI所有 Swing 按钮外观(ButtonUI)的基类,它位于 javax.swing.plaf.basic 包下,定义了按钮绘制、布局、事件处理的通用行为,而具体的外观差异(如颜色、边框、渐变)则由其子类(如 MetalButtonUIWindowsButtonUINimbusButtonUI 等)或自定义 UI 实现。

以下是关于 BasicButtonUI 的详细解析:

核心职责

BasicButtonUI 主要负责三件事:

  • 渲染:绘制按钮的背景、边框、文本和图标。
  • 布局:计算按钮中文本和图标的位置(通过 SwingUtilities.layoutCompoundLabel)。
  • 事件:处理鼠标按下/释放、键盘焦点、启用/禁用等状态变化,并触发重绘。

关键方法

方法 说明
installUI(JComponent c) 初始化UI,安装默认属性、监听器等。
uninstallUI(JComponent c) 卸载UI,清理监听器和属性。
paint(Graphics g, JComponent c) 主绘制入口,调用 paintButtonBackgroundpaintFocuspaintButtonBorderpaintTextpaintIcon
paintButtonBackground(...) 绘制背景,默认使用 ButtonUI.paintBackground 颜色。
paintFocus(...) 绘制焦点虚线框。
paintButtonBorder(...) 绘制按钮边框(默认为 BorderFactory.createRaisedBevelBorder() 等)。
paintText(...) 绘制文本,包含禁用状态下的灰色效果。
paintIcon(...) 绘制图标。
getPreferredSize(JComponent c) 返回按钮的最佳大小(基于文本+图标+边距)。

典型使用场景

1 继承并自定义按钮外观

如果你想创建一个扁平风格的按钮,可以重写 BasicButtonUI 的关键绘制方法:

import javax.swing.*;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;
public class FlatButtonUI extends BasicButtonUI {
    @Override
    public void paint(Graphics g, JComponent c) {
        AbstractButton b = (AbstractButton) c;
        ButtonModel model = b.getModel();
        // 1. 绘制自定义背景
        if (model.isPressed()) {
            g.setColor(new Color(180, 200, 230));  // 按下时颜色
        } else if (model.isRollover()) {
            g.setColor(new Color(220, 240, 255));  // 悬停时颜色
        } else {
            g.setColor(b.getBackground());
        }
        g.fillRect(0, 0, b.getWidth(), b.getHeight());
        // 2. 绘制文本和图标(调用父类方法)
        super.paint(g, c);
    }
    @Override
    protected void paintButtonBorder(Graphics g, AbstractButton b, int x, int y, int w, int h) {
        // 不绘制任何边框(扁平风格)
    }
    @Override
    protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
        // 不绘制焦点虚线
    }
}
// 使用
JButton btn = new JButton("扁平按钮");
btn.setUI(new FlatButtonUI());

2 修改默认行为

你可以通过重写 installUI 来改变按钮的默认属性(如边距、字体颜色等):

public class CustomButtonUI extends BasicButtonUI {
    @Override
    protected void installDefaults(AbstractButton b) {
        super.installDefaults(b);
        b.setMargin(new Insets(10, 20, 10, 20));  // 更大的内边距
        b.setFont(b.getFont().deriveFont(Font.BOLD)); // 加粗字体
    }
}

与系统外观的集成

BasicButtonUI 是所有平台外观的基类,但每个 LookAndFeel 会提供自己的子类:

  • WindowsButtonUI (com.sun.java.swing.plaf.windows) — Windows 原生风格。
  • MetalButtonUI (javax.swing.plaf.metal) — Metal 默认风格。
  • NimbusButtonUI (javax.swing.plaf.nimbus) — Nimbus 风格。
  • SynthButtonUI (javax.swing.plaf.synth) — 可配置皮肤风格。

直接使用 BasicButtonUI 通常意味着你希望完全自定义外观,而不是使用任何系统风格。

注意事项

  • 状态感知BasicButtonUI 内部会检查 ButtonModel 的状态(pressedrolloverarmedenabledselected 等),并在绘制时做出相应变化,如果你完全重写 paint 方法,可能丢失这些状态处理。
  • 计算位置BasicButtonUI 使用 SwingUtilities.layoutCompoundLabel 来计算文本和图标的位置,这个计算已考虑了水平/垂直对齐、边距、图标文本间隙等,推荐在自定义时复用此逻辑。
  • 性能:由于 BasicButtonUI 不自带任何缓存,如果频繁重绘(如动画),可能会产生性能问题,复杂的自定义 UI 可以考虑双缓冲或预渲染。

简单示例:完整扁平按钮 UI

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;
public class FlatButtonUI2 extends BasicButtonUI {
    private final Color normalColor = new Color(70, 130, 180);
    private final Color hoverColor = new Color(100, 160, 210);
    private final Color pressedColor = new Color(50, 100, 150);
    @Override
    public void installUI(JComponent c) {
        super.installUI(c);
        AbstractButton b = (AbstractButton) c;
        b.setOpaque(false);
        b.setBorder(new EmptyBorder(8, 16, 8, 16));
    }
    @Override
    public void paint(Graphics g, JComponent c) {
        AbstractButton b = (AbstractButton) c;
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int w = b.getWidth();
        int h = b.getHeight();
        // 绘制圆角矩形背景
        ButtonModel model = b.getModel();
        if (model.isPressed()) {
            g2.setColor(pressedColor);
        } else if (model.isRollover()) {
            g2.setColor(hoverColor);
        } else {
            g2.setColor(normalColor);
        }
        g2.fillRoundRect(0, 0, w, h, 8, 8);
        // 绘制文本(白色,居中)
        g2.setColor(Color.WHITE);
        FontMetrics fm = g2.getFontMetrics();
        String text = b.getText();
        int x = (w - fm.stringWidth(text)) / 2;
        int y = (h + fm.getAscent()) / 2 - 2;
        g2.drawString(text, x, y);
        g2.dispose();
    }
}
  • BasicButtonUI 是 Swing 按钮 UI 的 骨架,提供了标准流程但很少直接使用。
  • 当需要完全自定义按钮外观(颜色、形状、动画)时,继承 BasicButtonUI 并重写 paint 及辅助方法是常用做法。
  • 若只需轻微调整,应考虑继承特定 LookAndFeel 的 ButtonUI(如 MetalButtonUI),以保留系统原生风格。

抱歉,评论功能暂时关闭!