滑动开关作为现代UI设计的重要元素,在Swing中却缺乏原生支持。本文将详细介绍如何通过自绘方式实现一个功能完善的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);
}
}
状态管理:
外观绘制(paintComponent):
外观绘制(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;
});
本文详细解析了SwitchComponent的实现原理和使用方法,通过继承JComponent和自绘技术,开发者可以轻松为Swing应用添加现代化的滑动开关控件,有效提升用户交互体验。