Java Swing Timer无法停止问题求助
问题根源:变量作用域导致的Timer失控
兄弟,你这问题我一眼就看穿了——你在「Diashow」按钮的处理逻辑里,重新创建了一个局部的Timer变量,而没有使用类成员的timer!
具体来说:
- 你在类里声明了成员变量
Timer timer;,但在点击「Diashow」时,你写了Timer timer = new Timer(1000, new ActionListener() {...});——这里的Timer声明让这个timer变成了方法内的局部变量,和类成员的timer完全是两个独立的对象。 - 你启动的是这个局部
Timer,但点击「Stop」时,你调用的是类成员timer的stop()方法——可这个类成员timer从始至终都没被启动过!所以那个局部Timer就一直在后台跑,根本收不到停止指令。
修复方案
只需要修改「Diashow」分支的代码,删掉局部变量的声明,直接复用类成员的timer,同时最好在启动前先停止可能已经运行的Timer,避免多个Timer同时工作:
if (l.equals("Diashow")) { b0.setEnabled(false); b1.setEnabled(false); b2.setEnabled(false); b3.setEnabled(false); b4.setEnabled(true); // 先停止可能正在运行的Timer if (timer != null && timer.isRunning()) { timer.stop(); } // 直接使用类成员变量timer,不要重新声明 timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { p1.removeAll(); JLabel addit = new JLabel(new ImageIcon(imagelist.get(currentBild))); p1.add(addit); repaint(); revalidate(); currentBild = currentBild + 1; if (currentBild>=file.length) { currentBild=0; } } }); timer.start(); }
额外的优化建议
- 过时API替换:
getLabel()方法已经过时了,建议换成getText()来获取按钮的文本内容,让代码更规范。 - 异常处理优化:不要写空的
catch(Exception juckt2) { };,至少加上ex.printStackTrace();,这样出问题时能看到错误日志,方便调试。 - Java命名规范:类名应该采用大驼峰命名法,比如把
test3wegenDiashow改成PhotoViewer,变量名也尽量见名知意,提升代码可读性。 - 代码复用:可以把更新显示图片的逻辑封装成一个单独的方法,减少重复代码,比如
updateDisplayedImage(int index)。
修正后的完整代码
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import javax.imageio.ImageIO; public class PhotoViewer extends JFrame implements ActionListener, MouseListener { ArrayList<Image> imageList = new ArrayList<>(); ArrayList<Integer> imageIndices = new ArrayList<>(); JButton btnSelectImages, btnNext, btnPrevious, btnSlideshow, btnStop; JPanel panelButtons, panelImages; File[] selectedFiles; int currentImageIndex = 0; Timer slideshowTimer; public static void main(String[] args) { new PhotoViewer(); } public PhotoViewer() { super("Photoviewer"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 800); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); // 初始化按钮面板 panelButtons = new JPanel(new FlowLayout(FlowLayout.LEFT)); btnSelectImages = new JButton("Bilderauswahl"); btnSelectImages.addActionListener(this); btnNext = new JButton("Vorwärts"); btnNext.addActionListener(this); btnPrevious = new JButton("Rückwärts"); btnPrevious.addActionListener(this); btnSlideshow = new JButton("Diashow"); btnSlideshow.addActionListener(this); btnStop = new JButton("Stop"); btnStop.addActionListener(this); panelButtons.add(btnSelectImages); panelButtons.add(btnNext); panelButtons.add(btnPrevious); panelButtons.add(btnSlideshow); panelButtons.add(btnStop); contentPane.add(panelButtons, BorderLayout.SOUTH); // 初始化图片显示面板 panelImages = new JPanel(new FlowLayout(FlowLayout.LEFT)); contentPane.add(panelImages, BorderLayout.CENTER); // 初始禁用部分按钮 btnNext.setEnabled(false); btnPrevious.setEnabled(false); btnSlideshow.setEnabled(false); btnStop.setEnabled(false); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { JButton sourceBtn = (JButton) e.getSource(); String btnText = sourceBtn.getText(); if (btnText.equals("Bilderauswahl")) { panelImages.removeAll(); JFileChooser fileChooser = new JFileChooser(); fileChooser.setDialogTitle("Bilderauswahl"); FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG UND GIF", "jpg", "gif"); fileChooser.setFileFilter(filter); fileChooser.setMultiSelectionEnabled(true); int result = fileChooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { selectedFiles = fileChooser.getSelectedFiles(); imageList.clear(); imageIndices.clear(); for (int i = 0; i < selectedFiles.length; i++) { try { Image image = ImageIO.read(selectedFiles[i]); imageList.add(image); // 缩放图片 Image scaledImage = image.getScaledInstance(155, 155, Image.SCALE_SMOOTH); JLabel imageLabel = new JLabel(new ImageIcon(scaledImage)); imageLabel.setText("Bild " + (i + 1)); imageLabel.addMouseListener(this); panelImages.add(imageLabel); } catch (IOException ex) { ex.printStackTrace(); } } for (int z = 0; z < selectedFiles.length; z++) { imageIndices.add(z + 1); } panelImages.repaint(); panelImages.revalidate(); pack(); } } if (btnText.equals("Vorwärts")) { try { if (currentImageIndex >= 0 && currentImageIndex < selectedFiles.length - 1) { currentImageIndex++; updateDisplayedImage(currentImageIndex); } } catch (Exception ex) { ex.printStackTrace(); } } if (btnText.equals("Rückwärts")) { try { if (currentImageIndex > 0 && currentImageIndex <= selectedFiles.length - 1) { currentImageIndex--; updateDisplayedImage(currentImageIndex); } } catch (Exception ex) { ex.printStackTrace(); } } if (btnText.equals("Diashow")) { btnSelectImages.setEnabled(false); btnNext.setEnabled(false); btnPrevious.setEnabled(false); btnSlideshow.setEnabled(false); btnStop.setEnabled(true); // 停止已有Timer if (slideshowTimer != null && slideshowTimer.isRunning()) { slideshowTimer.stop(); } slideshowTimer = new Timer(1000, arg0 -> { updateDisplayedImage(currentImageIndex); currentImageIndex++; if (currentImageIndex >= selectedFiles.length) { currentImageIndex = 0; } }); slideshowTimer.start(); } if (btnText.equals("Stop")) { if (slideshowTimer != null && slideshowTimer.isRunning()) { slideshowTimer.stop(); } btnSelectImages.setEnabled(true); btnNext.setEnabled(true); btnPrevious.setEnabled(true); btnSlideshow.setEnabled(true); btnStop.setEnabled(false); } } // 封装更新显示图片的方法,减少重复代码 private void updateDisplayedImage(int index) { panelImages.removeAll(); JLabel imageLabel = new JLabel(new ImageIcon(imageList.get(index))); panelImages.add(imageLabel); panelImages.repaint(); panelImages.revalidate(); } @Override public void mouseClicked(MouseEvent e) { JLabel clickedLabel = (JLabel) e.getSource(); String labelText = clickedLabel.getText(); try { for (int y = 0; y < imageIndices.size(); y++) { if (labelText.equals("Bild " + imageIndices.get(y))) { btnNext.setEnabled(true); btnPrevious.setEnabled(true); btnSlideshow.setEnabled(true); btnStop.setEnabled(false); currentImageIndex = y; updateDisplayedImage(currentImageIndex); pack(); break; } } } catch (Exception ex) { ex.printStackTrace(); } } @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} }
内容的提问来源于stack exchange,提问作者Icantcodexd
相关产品推荐
相关产品推荐

