本文目录导读:

在 Java Swing 中,BasicButtonUI 是 所有 Swing 按钮外观(ButtonUI)的基类,它位于 javax.swing.plaf.basic 包下,定义了按钮绘制、布局、事件处理的通用行为,而具体的外观差异(如颜色、边框、渐变)则由其子类(如 MetalButtonUI、WindowsButtonUI、NimbusButtonUI 等)或自定义 UI 实现。
以下是关于 BasicButtonUI 的详细解析:
核心职责
BasicButtonUI 主要负责三件事:
- 渲染:绘制按钮的背景、边框、文本和图标。
- 布局:计算按钮中文本和图标的位置(通过
SwingUtilities.layoutCompoundLabel)。 - 事件:处理鼠标按下/释放、键盘焦点、启用/禁用等状态变化,并触发重绘。
关键方法
| 方法 | 说明 |
|---|---|
installUI(JComponent c) |
初始化UI,安装默认属性、监听器等。 |
uninstallUI(JComponent c) |
卸载UI,清理监听器和属性。 |
paint(Graphics g, JComponent c) |
主绘制入口,调用 paintButtonBackground、paintFocus、paintButtonBorder、paintText、paintIcon。 |
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的状态(pressed、rollover、armed、enabled、selected等),并在绘制时做出相应变化,如果你完全重写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),以保留系统原生风格。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播