You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
}
额外的优化建议
  1. 过时API替换:getLabel()方法已经过时了,建议换成getText()来获取按钮的文本内容,让代码更规范。
  2. 异常处理优化:不要写空的catch(Exception juckt2) { };,至少加上ex.printStackTrace();,这样出问题时能看到错误日志,方便调试。
  3. Java命名规范:类名应该采用大驼峰命名法,比如把test3wegenDiashow改成PhotoViewer,变量名也尽量见名知意,提升代码可读性。
  4. 代码复用:可以把更新显示图片的逻辑封装成一个单独的方法,减少重复代码,比如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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:17:32