如何让 Java 程序在侦听器工作时等待?

How to make Java program wait while a listener is working?

我的程序中有一个 JSlider。当滑块的值改变时,程序会做一些事情。我想要做的是将滑块的值增加到它的最大值,每次滑块值增加时我都需要等待我在 ChangeListener class.

中所做的事情

这是我的相关代码(svPlay就像一个播放按钮):

this.svPlay.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            for(int i=slider.getValue()+1;i<=slider.getMaximum();i++){
                slider.setValue(i);
                try{
                    Thread.sleep(1000);
                }catch (Exception ex){
                    ex.printStackTrace();
                }
            }
        }
    });

问题是,例如,如果 i=10,则程序等待 10*1000(我使用 sleep() 方法的毫秒数),它会同时执行所有 changeListener 作业。

在 slider.setValue(i) 之后,changeListener 必须工作,然后程序应该休眠 1000 毫秒。我该怎么做?

编辑:这就是我根据上面的代码更改程序的方式。但是现在更改滑块值和滑块 "freezes".

时什么也没有发生
this.slider.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            new Thread(() -> {
                try {
                    synchronized (lock) {
                        Thread.sleep(1234);
                        if(checkBox.isSelected()){
                            CyApplicationManager manager = adapter.getCyApplicationManager();
                            CyNetworkView networkView = manager.getCurrentNetworkView();
                            CyNetwork network = networkView.getModel();
                            CyTable table = network.getDefaultNodeTable();
                            FilterUtil filter = new FilterUtil(network,table);
                            ArrayList<CyNode> activities = filter.FilterRowByNodeType("activity", "nodeType");

                            CyColumn timeColumn = table.getColumn("startTime"); // Getting start time column
                            List<String> timeList = filter.getTimeFromColumn(timeColumn); // Gets value of start time column without null value
                            sliderVisualization.sortActivityTimes(timeList, activities);
                            sliderLabel.setText(timeList.get(slider.getValue()));
                            sliderVisualization.hideFutureNodes(timeList, filter, network, networkView);
                            networkView.updateView();
                        }
                        lock.notify();
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }).start();

        }
    });

    this.svPlay.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            new Thread(() -> {
                slider.setEnabled(false);
                for(int i=slider.getValue()+1;i<=slider.getMaximum();i++){
                    synchronized (lock) {
                        slider.setValue(i);
                        try {
                            lock.wait();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }
                slider.setEnabled(true);
            }).start();
        }
    });

我在 addChangeListener 方法中的 Thread.sleep() 之前和之后放置了 if 语句,但这两种方式都不起作用。我不知道我转换得好不好。你能帮我看看这段代码吗?

这是我从您的问题中了解到的:您在 Slider 更改侦听器中进行了长时间的计算。您想要对一系列值执行计算,并将其反映在滑块上。

如果上述前提是正确的,您不想在计算进行时休眠 n 秒——您想等待它们完成并尽快继续。一种方法是在锁上使用等待和通知命令(注意,最近的 Java 带有 java.util.concurrent 包,它包含更高级别的多线程控制,我认为使用起来会更好,但是我自己也不熟悉)

package testas;

import javax.swing.*;

public class Slider {

    static class View {

        public JPanel panel;
        public JSlider slider;
        public JButton button;
        public JTextField tf;

        public View() {
            panel = new JPanel();
            button = new JButton("a");
            slider = new JSlider();
            tf = new JTextField(4);
            panel.add(button);
            panel.add(slider);
            panel.add(tf);
        }


    }

    static class Controller {

        private Object lock;
        private View view;

        public Controller() {
            lock = new Object();
        }

        private synchronized void buttonHandler() {
            new Thread(() -> {
                view.slider.setEnabled(false);
                for(int i=view.slider.getValue()+1;i<=view.slider.getMaximum();i++){
                    synchronized (lock) {
                        view.slider.setValue(i);
                        try {
                            lock.wait();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                view.slider.setEnabled(true);
            }).start();
        }

        private synchronized void sliderChangeHandler(int value) {
            new Thread(() -> {
                try {
                    synchronized (lock) {
                        Thread.sleep(1234);//some long calculations
                        view.tf.setText(String.valueOf(value));
                        lock.notify();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } 
            }).start();
        }

        public void setView(View v) {

            view = v;
            v.button.addActionListener(l -> buttonHandler());
            v.slider.addChangeListener(l -> {
                JSlider slider = (JSlider) l.getSource();
                if (!slider.getValueIsAdjusting())
                    sliderChangeHandler(slider.getValue());
            });
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Controller c = new Controller();
            View v = new View();
            c.setView(v);
            JFrame f = new JFrame();
            f.add(v.panel);
            f.pack();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setVisible(true);
        });
    }
}