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

时间:2017-10-21 16:17:55

标签: java listener jslider

我的程序中有一个JSlider。当滑块的值改变时,程序会执行某些操作。我想要做的是增加滑块的值直到它的最大值,我需要等待每次滑块值增加我在ChangeListener类中做的事情。

这是我的相关代码(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毫秒。我怎么能这样做?

编辑:根据上面的代码,这是我改变程序的方式。但是现在当滑块值改变并且滑块“冻结”时,没有任何事情发生。

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语句放在了但是两种方式都没有用。我不知道我是否将其转换得很好。你能帮忙解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

这是我从你的问题中理解的:你在Slider change listener中进行了长时间的计算。您想要对一系列值执行计算,并在滑块上反映出来。

如果上述前提是正确的,那么在计算过程中你不想睡n秒 - 你想等待它们完成并尽快继续。一种方法是在锁上使用wait和notify命令(注意,最近的Java附带了java.util.concurrent包,其中包含更高级别的多线程控件,我认为最好使用,但是我&#39;我自己并不熟悉)

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);
        });
    }
}