Java Swing 自定义组件库分享(九)
Java Swing 自定义组件库分享(九):滑动开关 — SwitchComponent
- 一、背景
- 二、核心设计
- 三、类源码
- 四、核心功能说明
- 五、使用示例
- 六、注意事项
- 七、小结
一、背景
在 Web 端和移动端应用中,滑动开关(Toggle Switch)是一种常见的 UI 交互组件,用于切换开启/关闭状态。Swing 原生没有提供类似的组件,通常只能用复选框(JCheckBox)来模拟,但样式陈旧且不够直观。
SwitchComponent 的作用就是:自绘一个滑动开关组件,支持开启/关闭状态切换、禁用状态、自定义颜色和文字,提供更现代的交互体验。
二、核心设计
SwitchComponent 继承 JComponent,通过重写 paintComponent 方法自绘开关外观,包括背景圆角矩形、圆形滑块和 ON/OFF 文字。
开启状态:绿色背景,滑块在右侧,显示 “ON”
关闭状态:灰色背景,滑块在左侧,显示 “OFF”
禁用状态:浅灰色背景,不响应点击
三、类源码
importjavax.swing.*;importjava.awt.*;importjava.awt.event.MouseAdapter;importjava.awt.event.MouseEvent;/** * 滑动开关组件 * 自绘实现,支持开启/关闭状态切换、禁用状态、文字显示 * * 使用示例: * SwitchComponent sw = new SwitchComponent(); * sw.setSwitched(true); * sw.addMouseListener(new MouseAdapter() { * public void mouseClicked(MouseEvent e) { * System.out.println("状态:" + sw.isSwitched()); * } * }); */publicclassSwitchComponentextendsJComponent{/** 开关状态 */privatebooleanswitched=false;/** 是否启用 */privatebooleanenabled=true;/** * 构造函数 */publicSwitchComponent(){setPreferredSize(newDimension(60,25));setOpaque(false);setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));addMouseListener(newMouseAdapter(){@OverridepublicvoidmouseClicked(MouseEvente){if(enabled){switched=!switched;repaint();// 触发父容器的重绘Containerparent=getParent();if(parent!=null){parent.repaint();}}}@OverridepublicvoidmouseEntered(MouseEvente){if(enabled){setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));}else{setCursor(Cursor.getDefaultCursor());}}});}/** * 获取开关状态 * @return true=开启,false=关闭 */publicbooleanisSwitched(){returnswitched;}/** * 设置开关状态 * @param switched 状态 */publicvoidsetSwitched(booleanswitched){this.switched=switched;repaint();}/** * 设置是否启用 * @param enabled 是否启用 */@OverridepublicvoidsetEnabled(booleanenabled){this.enabled=enabled;repaint();}@OverrideprotectedvoidpaintComponent(Graphicsg){Graphics2Dg2=(Graphics2D)g;g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);intwidth=getWidth();intheight=getHeight();// 绘制背景ColorbgColor;if(!enabled){bgColor=Color.LIGHT_GRAY;}elseif(switched){bgColor=Color.decode("#67C23A");// 开启状态绿色}else{bgColor=Color.decode("#DCDFE6");// 关闭状态灰色}g2.setColor(bgColor);g2.fillRoundRect(0,0,width,height,height,height);// 绘制圆形滑块ColorknobColor=Color.WHITE;intknobDiameter=height-4;intknobX=switched?width-knobDiameter-2:2;g2.setColor(knobColor);g2.fillOval(knobX,2,knobDiameter,knobDiameter);// 添加阴影效果g2.setColor(newColor(0,0,0,30));g2.drawOval(knobX,2,knobDiameter,knobDiameter);// 绘制开关文字g2.setColor(enabled?Color.WHITE:Color.GRAY);g2.setFont(getFont().deriveFont(Font.BOLD,10f));FontMetricsfm=g2.getFontMetrics();Stringtext=switched?"ON":"OFF";inttextWidth=fm.stringWidth(text);inttextX=switched?6:width-textWidth-6;inttextY=height/2+fm.getAscent()/2;g2.drawString(text,textX,textY);}}四、核心功能说明
状态管理:
- switched:开关状态(true=开启,false=关闭)
- enabled:是否启用(禁用时不响应点击,显示灰色)
- isSwitched() / setSwitched():获取/设置状态
- setEnabled():设置启用状态
外观绘制(paintComponent):
- 背景:圆角矩形,根据状态(开启/关闭/禁用)使用不同颜色
- 滑块:圆形,根据状态移动到左侧或右侧,带轻微阴影
- 文字:ON(开启)显示在左侧,OFF(关闭)显示在右侧
外观绘制(paintComponent):
- 鼠标点击时切换状态并重绘
- 悬停时显示手型光标
- 禁用状态下光标为默认样式
五、使用示例
5.1 基本用法
SwitchComponentsw=newSwitchComponent();panel.add(sw);5.2 设置初始状态
SwitchComponentsw=newSwitchComponent();sw.setSwitched(true);// 默认开启panel.add(sw);5.3 监听状态变化
SwitchComponentsw=newSwitchComponent();sw.addMouseListener(newMouseAdapter(){@OverridepublicvoidmouseClicked(MouseEvente){System.out.println("开关状态:"+(sw.isSwitched()?"开启":"关闭"));}});5.4 禁用开关
SwitchComponentsw=newSwitchComponent();sw.setEnabled(false);panel.add(sw);5.5 自定义尺寸(通过 setPreferredSize)
SwitchComponentsw=newSwitchComponent();sw.setPreferredSize(newDimension(80,30));panel.add(sw);5.6 配合表格使用(见后续表格篇章)
// 在表格的开关列中使用SwitchCellEditoreditor=newSwitchCellEditor(metTable,(row,newState)->{System.out.println("第"+row+"行状态变为:"+newState);returntrue;});六、注意事项
- 尺寸默认值:默认尺寸为 60x25,可通过 setPreferredSize 调整
- 文字语言:默认显示 “ON”/“OFF”,可根据需要修改 paintComponent 中的文字
- 颜色值:开启状态绿色 #67C23A 为 Element UI 风格,可根据主题自行调整
- 父容器重绘:点击切换后主动调用父容器 repaint(),确保父容器刷新
- 透明背景:setOpaque(false) 让组件背景透明,便于融入不同背景的父容器
七、小结
SwitchComponent 是一个自绘的滑动开关组件,通过 paintComponent 实现完整外观,支持开启/关闭状态切换、禁用状态、文字显示和悬停光标效果。
核心实现要点:
- 继承 JComponent 而非 JToggleButton,完全自绘控制外观
- paintComponent 中根据状态绘制不同颜色和滑块位置
- 鼠标点击事件中切换状态并重绘
