最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java Swing自定义组件库系列第九篇
时间:2026-05-29 12:15:01 编辑:袖梨 来源:一聚教程网
滑动开关作为现代UI设计的重要元素,在Swing中却缺乏原生支持。本文将详细介绍如何通过自绘方式实现一个功能完善的SwitchComponent组件。
滑动开关 — SwitchComponent
一、背景
现代应用界面中,滑动开关已成为常见的交互控件。由于Swing框架未提供原生支持,开发者通常只能使用JCheckBox进行模拟。SwitchComponent通过自绘方式解决了这个问题,支持状态切换、禁用模式、自定义颜色和文字,为Swing应用带来更直观的操作体验。

二、核心设计
该组件继承自JComponent,通过重写paintComponent方法实现完整绘制功能。开启状态采用绿色背景,滑块位于右侧并显示"ON"文字;关闭状态则为灰色背景,滑块位于左侧显示"OFF";禁用状态下组件呈现浅灰色且不响应操作。
三、类源码
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;/**
* 滑动开关组件
* 自绘实现,支持开启/关闭状态切换、禁用状态、文字显示
* * 使用示例:
* SwitchComponent sw = new SwitchComponent();
* sw.setSwitched(true);
* sw.addMouseListener(new MouseAdapter() {
* public void mouseClicked(MouseEvent e) {
* System.out.println("状态:" + sw.isSwitched());
* }
* });
*/
public class SwitchComponent extends JComponent {
/** 开关状态 */
private boolean switched = false;
/** 是否启用 */
private boolean enabled = true; /**
* 构造函数
*/
public SwitchComponent() {
setPreferredSize(new Dimension(60, 25));
setOpaque(false);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (enabled) {
switched = !switched;
repaint();
// 触发父容器的重绘
Container parent = getParent();
if (parent != null) {
parent.repaint();
}
}
} @Override
public void mouseEntered(MouseEvent e) {
if (enabled) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else {
setCursor(Cursor.getDefaultCursor());
}
}
});
} /**
* 获取开关状态
* @return true=开启,false=关闭
*/
public boolean isSwitched() {
return switched;
} /**
* 设置开关状态
* @param switched 状态
*/
public void setSwitched(boolean switched) {
this.switched = switched;
repaint();
} /**
* 设置是否启用
* @param enabled 是否启用
*/
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
repaint();
} @Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int width = getWidth();
int height = getHeight(); // 绘制背景
Color bgColor;
if (!enabled) {
bgColor = Color.LIGHT_GRAY;
} else if (switched) {
bgColor = Color.decode("#67C23A"); // 开启状态绿色
} else {
bgColor = Color.decode("#DCDFE6"); // 关闭状态灰色
} g2.setColor(bgColor);
g2.fillRoundRect(0, 0, width, height, height, height); // 绘制圆形滑块
Color knobColor = Color.WHITE;
int knobDiameter = height - 4;
int knobX = switched ? width - knobDiameter - 2 : 2; g2.setColor(knobColor);
g2.fillOval(knobX, 2, knobDiameter, knobDiameter); // 添加阴影效果
g2.setColor(new Color(0, 0, 0, 30));
g2.drawOval(knobX, 2, knobDiameter, knobDiameter); // 绘制开关文字
g2.setColor(enabled ? Color.WHITE : Color.GRAY);
g2.setFont(getFont().deriveFont(Font.BOLD, 10f));
FontMetrics fm = g2.getFontMetrics();
String text = switched ? "ON" : "OFF";
int textWidth = fm.stringWidth(text);
int textX = switched ? 6 : width - textWidth - 6;
int textY = height / 2 + fm.getAscent() / 2; g2.drawString(text, textX, textY);
}
}
四、核心功能说明
状态管理:
- switched:开关状态(true=开启,false=关闭)
- enabled:是否启用(禁用时不响应点击,显示灰色)
- isSwitched() / setSwitched():获取/设置状态
- setEnabled():设置启用状态
外观绘制(paintComponent):
- 背景:圆角矩形,根据状态(开启/关闭/禁用)使用不同颜色
- 滑块:圆形,根据状态移动到左侧或右侧,带轻微阴影
- 文字:ON(开启)显示在左侧,OFF(关闭)显示在右侧
外观绘制(paintComponent):
- 鼠标点击时切换状态并重绘
- 悬停时显示手型光标
- 禁用状态下光标为默认样式
五、使用示例
5.1 基本用法
SwitchComponent sw = new SwitchComponent();
panel.add(sw);
5.2 设置初始状态
SwitchComponent sw = new SwitchComponent();
sw.setSwitched(true); // 默认开启
panel.add(sw);
5.3 状态变化
SwitchComponent sw = new SwitchComponent();
sw.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("开关状态:" + (sw.isSwitched() ? "开启" : "关闭"));
}
});
5.4 禁用开关
SwitchComponent sw = new SwitchComponent();
sw.setEnabled(false);
panel.add(sw);
5.5 自定义尺寸(通过 setPreferredSize)
SwitchComponent sw = new SwitchComponent();
sw.setPreferredSize(new Dimension(80, 30));
panel.add(sw);
5.6 配合表格使用(见后续表格篇章)
// 在表格的开关列中使用
SwitchCellEditor editor = new SwitchCellEditor(metTable, (row, newState) -> {
System.out.println("第" + row + "行状态变为:" + newState);
return true;
});
六、注意事项
- 尺寸默认值:默认尺寸为 60x25,可通过 setPreferredSize 调整
- 文字语言:默认显示 "ON"/"OFF",可根据需要修改 paintComponent 中的文字
- 颜色值:开启状态绿色 #67C23A 为 Element UI 风格,可根据主题自行调整
- 父容器重绘:点击切换后主动调用父容器 repaint(),确保父容器刷新
- 透明背景:setOpaque(false) 让组件背景透明,便于融入不同背景的父容器
七、小结
本文详细解析了SwitchComponent的实现原理和使用方法,通过继承JComponent和自绘技术,开发者可以轻松为Swing应用添加现代化的滑动开关控件,有效提升用户交互体验。