一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Java Swing自定义组件库系列第九篇

时间:2026-05-29 12:15:01 编辑:袖梨 来源:一聚教程网

滑动开关作为现代UI设计的重要元素,在Swing中却缺乏原生支持。本文将详细介绍如何通过自绘方式实现一个功能完善的SwitchComponent组件。

滑动开关 — SwitchComponent

一、背景

现代应用界面中,滑动开关已成为常见的交互控件。由于Swing框架未提供原生支持,开发者通常只能使用JCheckBox进行模拟。SwitchComponent通过自绘方式解决了这个问题,支持状态切换、禁用模式、自定义颜色和文字,为Swing应用带来更直观的操作体验。

Java 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);
    }
}

四、核心功能说明

状态管理:

  1. switched:开关状态(true=开启,false=关闭)
  2. enabled:是否启用(禁用时不响应点击,显示灰色)
  3. isSwitched() / setSwitched():获取/设置状态
  4. setEnabled():设置启用状态

外观绘制(paintComponent):

  1. 背景:圆角矩形,根据状态(开启/关闭/禁用)使用不同颜色
  2. 滑块:圆形,根据状态移动到左侧或右侧,带轻微阴影
  3. 文字:ON(开启)显示在左侧,OFF(关闭)显示在右侧

外观绘制(paintComponent):

  1. 鼠标点击时切换状态并重绘
  2. 悬停时显示手型光标
  3. 禁用状态下光标为默认样式

五、使用示例

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;
});

六、注意事项

  1. 尺寸默认值:默认尺寸为 60x25,可通过 setPreferredSize 调整
  2. 文字语言:默认显示 "ON"/"OFF",可根据需要修改 paintComponent 中的文字
  3. 颜色值:开启状态绿色 #67C23A 为 Element UI 风格,可根据主题自行调整
  4. 父容器重绘:点击切换后主动调用父容器 repaint(),确保父容器刷新
  5. 透明背景:setOpaque(false) 让组件背景透明,便于融入不同背景的父容器

七、小结

本文详细解析了SwitchComponent的实现原理和使用方法,通过继承JComponent和自绘技术,开发者可以轻松为Swing应用添加现代化的滑动开关控件,有效提升用户交互体验。

热门栏目