Java Swing开发:实现单按钮控制10个功能按钮停止功能
解决方案
核心实现要点
- 避免在Swing事件线程中执行耗时操作,所有按钮的运行逻辑都放在后台线程中
- 通过
volatile修饰的布尔变量控制所有任务的启停,保证线程间的状态可见性 - 用集合统一管理所有后台线程,方便停止时批量处理
修改后的完整代码
package dc.android.doctor.v3; import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.List; public class DCJFrame extends javax.swing.JFrame { // 全局停止标志,volatile保证线程可见性 private volatile boolean isRunning = false; // 存储所有后台任务线程 private List<Thread> taskThreads = new ArrayList<>(); public DCJFrame() { initComponents(); // 给10个按钮绑定各自的功能监听器 initButtonActions(); } private void initButtonActions() { // 按钮1:正向更新进度条 jButton1.addActionListener(e -> runTask(() -> { for (int i = 0; i <= 100 && isRunning; i++) { int finalI = i; SwingUtilities.invokeLater(() -> jProgressBar1.setValue(finalI)); try { Thread.sleep(50); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } })); // 按钮2:弹出消息对话框 jButton2.addActionListener(e -> runTask(() -> { SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(this, "按钮2任务执行中")); try { Thread.sleep(2000); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(this, "按钮2任务完成")); })); // 按钮3:循环修改自身文本计数 jButton3.addActionListener(e -> runTask(() -> { int count = 0; while (isRunning) { String text = "按钮3计数:" + count++; SwingUtilities.invokeLater(() -> jButton3.setText(text)); try { Thread.sleep(1000); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } } SwingUtilities.invokeLater(() -> jButton3.setText("jButton3")); })); // 按钮4:控制台循环计数输出 jButton4.addActionListener(e -> runTask(() -> { int count = 0; while (isRunning) { System.out.println("按钮4计数:" + count++); try { Thread.sleep(800); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } } })); // 按钮5:循环修改窗口标题 jButton5.addActionListener(e -> runTask(() -> { int count = 0; while (isRunning) { String title = "动态标题-" + count++; SwingUtilities.invokeLater(() -> setTitle(title)); try { Thread.sleep(1200); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } } SwingUtilities.invokeLater(() -> setTitle("DCJFrame")); })); // 按钮6:循环切换自身背景色 jButton6.addActionListener(e -> runTask(() -> { Color[] colors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW}; int index = 0; while (isRunning) { Color color = colors[index++ % colors.length]; SwingUtilities.invokeLater(() -> jButton6.setBackground(color)); try { Thread.sleep(1500); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } } SwingUtilities.invokeLater(() -> jButton6.setBackground(UIManager.getColor("Button.background"))); })); // 按钮7:打开新窗口,5秒后自动关闭 jButton7.addActionListener(e -> runTask(() -> { SwingUtilities.invokeLater(() -> { JFrame newFrame = new JFrame("按钮7的新窗口"); newFrame.setSize(300, 200); newFrame.setLocationRelativeTo(this); newFrame.add(new JLabel("这是按钮7触发的新窗口")); newFrame.setVisible(true); }); try { Thread.sleep(5000); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } SwingUtilities.invokeLater(() -> { for (Window window : Window.getWindows()) { if (window != this && window instanceof JFrame) { window.dispose(); } } }); })); // 按钮8:控制台输出随机数 jButton8.addActionListener(e -> runTask(() -> { while (isRunning) { int random = (int) (Math.random() * 1000); System.out.println("按钮8生成随机数:" + random); try { Thread.sleep(600); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } } })); // 按钮9:反向更新进度条 jButton9.addActionListener(e -> runTask(() -> { for (int i = 100; i >= 0 && isRunning; i--) { int finalI = i; SwingUtilities.invokeLater(() -> jProgressBar1.setValue(finalI)); try { Thread.sleep(50); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } })); // 按钮10:循环切换前3个按钮的启用状态 jButton10.addActionListener(e -> runTask(() -> { boolean enabled = true; while (isRunning) { boolean finalEnabled = enabled; SwingUtilities.invokeLater(() -> { jButton1.setEnabled(finalEnabled); jButton2.setEnabled(finalEnabled); jButton3.setEnabled(finalEnabled); }); enabled = !enabled; try { Thread.sleep(2000); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } } SwingUtilities.invokeLater(() -> { jButton1.setEnabled(true); jButton2.setEnabled(true); jButton3.setEnabled(true); }); })); } // 通用任务启动方法 private void runTask(Runnable task) { if (isRunning) { Thread thread = new Thread(task); taskThreads.add(thread); thread.start(); } } @SuppressWarnings("unchecked") private void initComponents() { jButton1 = new javax.swing.JButton(); jButton2 = new javax.swing.JButton(); jButton3 = new javax.swing.JButton(); jButton4 = new javax.swing.JButton(); jButton5 = new javax.swing.JButton(); jButton6 = new javax.swing.JButton(); jButton7 = new javax.swing.JButton(); jButton8 = new javax.swing.JButton(); jButton9 = new javax.swing.JButton(); jButton10 = new javax.swing.JButton(); jProgressBar1 = new javax.swing.JProgressBar(); start = new javax.swing.JButton(); stop = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jButton1.setText("jButton1"); jButton2.setText("jButton2"); jButton3.setText("jButton3"); jButton4.setText("jButton4"); jButton5.setText("jButton5"); jButton6.setText("jButton6"); jButton7.setText("jButton7"); jButton8.setText("jButton8"); jButton9.setText("jButton9"); jButton10.setText("jButton10"); start.setText("START"); start.addActionListener(e -> startActionPerformed(e)); stop.setText("STOP"); stop.addActionListener(e -> stopActionPerformed(e)); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(jButton1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addComponent(jButton6) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton7) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton8) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton9) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton10) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addComponent(start) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(stop))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(25, 25, 25) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jButton1) .addComponent(jButton2) .addComponent(jButton3) .addComponent(jButton4) .addComponent(jButton5)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jButton6) .addComponent(jButton7) .addComponent(jButton8) .addComponent(jButton9) .addComponent(jButton10)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 146, Short.MAX_VALUE) .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(start) .addComponent(stop)) .addGap(17, 17, 17)) ); pack(); } private void startActionPerformed(java.awt.event.ActionEvent evt) { isRunning = true; taskThreads.clear(); // 重置进度条 SwingUtilities.invokeLater(() -> jProgressBar1.setValue(0)); JOptionPane.showMessageDialog(this, "已启动所有任务,点击按钮开始执行"); } private void stopActionPerformed(java.awt.event.ActionEvent evt) { isRunning = false; // 中断所有线程 for (Thread thread : taskThreads) { thread.interrupt(); } taskThreads.clear(); // 恢复界面状态 SwingUtilities.invokeLater(() -> { jProgressBar1.setValue(0); setTitle("DCJFrame"); jButton3.setText("jButton3"); jButton6.setBackground(UIManager.getColor("Button.background")); jButton1.setEnabled(true); jButton2.setEnabled(true); jButton3.setEnabled(true); // 关闭所有打开的新窗口 for (Window window : Window.getWindows()) { if (window != this && window instanceof JFrame) { window.dispose(); } } }); JOptionPane.showMessageDialog(this, "已停止所有任务"); } public static void main(String args[]) { try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(DCJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } java.awt.EventQueue.invokeLater(() -> new DCJFrame().setVisible(true)); } private javax.swing.JButton jButton1; private javax.swing.JButton jButton10; private javax.swing.JButton jButton2; private javax.swing.JButton jButton3; private javax.swing.JButton jButton4; private javax.swing.JButton jButton5; private javax.swing.JButton jButton6; private javax.swing.JButton jButton7; private javax.swing.JButton jButton8; private javax.swing.JButton jButton9; private javax.swing.JProgressBar jProgressBar1; private javax.swing.JButton start; private javax.swing.JButton stop; }
关键代码说明
- 线程安全控制:用
volatile boolean isRunning作为全局开关,所有后台任务都会循环检查这个变量,一旦变为false就终止执行 - 任务管理:
taskThreads集合存储所有启动的后台线程,停止时批量中断并清空 - Swing线程规则:所有修改UI的操作必须通过
SwingUtilities.invokeLater()提交到事件线程执行,避免线程安全问题 - 按钮功能:10个按钮分别实现了进度条更新、弹窗、文本修改、控制台输出、窗口标题变化、背景色切换、新窗口打开、随机数生成、反向进度条、按钮状态切换等不同功能
- 启停逻辑:
- START按钮:设置
isRunning=true,清空线程列表,重置界面状态 - STOP按钮:设置
isRunning=false,中断所有线程,恢复所有界面元素到初始状态
- START按钮:设置
内容的提问来源于stack exchange,提问作者DISCOUNT CENTRE
相关产品推荐
相关产品推荐

