Java实现互斥切换开关:三开关启一则其余两关的方法
嘿,这个需求本质就是做一组互斥的切换开关——同一时间只能有一个处于开启状态,其他自动关闭。下面我给你分别用JavaFX和Swing这两个最常用的Java UI框架来实现,代码都是可以直接运行的~
JavaFX实现方案
JavaFX里自带ToggleGroup组件,专门用来管理一组互斥的Toggle控件,搭配ToggleButton并自定义样式就能做成开关的样子,非常省心:
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class MutexToggleSwitches extends Application { @Override public void start(Stage primaryStage) { // 创建ToggleGroup,核心就是靠它实现互斥逻辑 ToggleGroup toggleGroup = new ToggleGroup(); // 创建三个切换开关(本质是带样式的ToggleButton) ToggleButton switch1 = new ToggleButton("选项1"); ToggleButton switch2 = new ToggleButton("选项2"); ToggleButton switch3 = new ToggleButton("选项3"); // 把三个开关加入同一个组,自动实现"开一个关其他"的效果 switch1.setToggleGroup(toggleGroup); switch2.setToggleGroup(toggleGroup); switch3.setToggleGroup(toggleGroup); // 给开关加样式,改成常见的滑动开关外观 String switchStyle = """ .toggle-button { -fx-background-color: #ccc; -fx-background-radius: 20px; -fx-min-width: 60px; -fx-min-height: 30px; -fx-text-fill: transparent; } .toggle-button:selected { -fx-background-color: #4CAF50; } .toggle-button .text { -fx-translate-x: -20px; } .toggle-button:selected .text { -fx-translate-x: 20px; -fx-fill: white; } """; // 应用样式到每个开关 switch1.setStyle(switchStyle); switch2.setStyle(switchStyle); switch3.setStyle(switchStyle); // 监听选中状态变化,方便调试看效果 toggleGroup.selectedToggleProperty().addListener((obs, oldVal, newVal) -> { if (newVal != null) { System.out.println("选中了:" + ((ToggleButton) newVal).getText()); } }); // 用VBox布局放开关,加 padding 让界面不拥挤 VBox vbox = new VBox(10, switch1, switch2, switch3); vbox.setPadding(new javafx.geometry.Insets(20)); Scene scene = new Scene(vbox, 200, 150); primaryStage.setTitle("互斥切换开关"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
关键说明
ToggleGroup是核心,只要把Toggle控件加入同一组,就会自动处理互斥逻辑,完全不用自己写判断代码。- 上面的CSS样式可以根据你的需求调整,比如改开关颜色、大小、文字位置,很灵活。
Swing实现方案
Swing没有原生的ToggleSwitch控件,但我们可以自定义JToggleButton的绘制逻辑,模拟开关样式,再用ButtonGroup实现互斥:
import javax.swing.*; import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; public class MutexSwingSwitches extends JFrame { public MutexSwingSwitches() { setTitle("互斥切换开关"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); setPadding(20); // 创建ButtonGroup,管理互斥逻辑 ButtonGroup buttonGroup = new ButtonGroup(); // 创建三个自定义开关 CustomToggleSwitch switch1 = new CustomToggleSwitch("选项1"); CustomToggleSwitch switch2 = new CustomToggleSwitch("选项2"); CustomToggleSwitch switch3 = new CustomToggleSwitch("选项3"); // 加入同一个ButtonGroup,实现互斥 buttonGroup.add(switch1); buttonGroup.add(switch2); buttonGroup.add(switch3); // 添加状态监听,打印选中结果 ItemListener listener = e -> { CustomToggleSwitch source = (CustomToggleSwitch) e.getSource(); if (e.getStateChange() == ItemEvent.SELECTED) { System.out.println("选中了:" + source.getText()); } }; switch1.addItemListener(listener); switch2.addItemListener(listener); switch3.addItemListener(listener); // 把开关加到窗口里,加间距让界面更美观 add(switch1); add(Box.createVerticalStrut(10)); add(switch2); add(Box.createVerticalStrut(10)); add(switch3); pack(); setLocationRelativeTo(null); } // 自定义开关组件,继承JToggleButton手动绘制样式 static class CustomToggleSwitch extends JToggleButton { private static final int WIDTH = 60; private static final int HEIGHT = 30; private static final int KNOB_SIZE = 26; public CustomToggleSwitch(String text) { super(text); setPreferredSize(new Dimension(WIDTH + 80, HEIGHT)); // 留空间放文字 setBorderPainted(false); setContentAreaFilled(false); setFocusPainted(false); } @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 绘制开关背景 int x = 10; int y = (getHeight() - HEIGHT) / 2; g2.setColor(isSelected() ? new Color(76, 175, 80) : Color.LIGHT_GRAY); g2.fillRoundRect(x, y, WIDTH, HEIGHT, HEIGHT, HEIGHT); // 绘制开关旋钮 int knobX = isSelected() ? x + WIDTH - KNOB_SIZE - 2 : x + 2; int knobY = y + (HEIGHT - KNOB_SIZE) / 2; g2.setColor(Color.WHITE); g2.fillOval(knobX, knobY, KNOB_SIZE, KNOB_SIZE); // 绘制开关文字 g2.setColor(isSelected() ? Color.WHITE : Color.BLACK); g2.drawString(getText(), x + WIDTH + 10, y + HEIGHT / 2 + g2.getFontMetrics().getAscent() / 2); g2.dispose(); super.paintComponent(g); } } private void setPadding(int padding) { getContentPane().setBorder(BorderFactory.createEmptyBorder(padding, padding, padding, padding)); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new MutexSwingSwitches().setVisible(true)); } }
关键说明
ButtonGroup和JavaFX的ToggleGroup作用一致,把多个JToggleButton加入同一组后,就会自动互斥。- 自定义的
CustomToggleSwitch重写了paintComponent方法,手动绘制了开关的背景和旋钮,你可以调整颜色、尺寸来适配自己的UI风格。
内容的提问来源于stack exchange,提问作者Mourad El
相关产品推荐
相关产品推荐

