更改侦听器在JSlider中创建阻碍

时间:2014-07-06 20:43:59

标签: java swing clip jslider

我已经编写了这个用于播放音乐的代码,JSlider随着音乐的进展自动向前移动,我已经为JSlider添加了更改侦听器,用于通过光标改变音乐位置,问题是当JSlider的nob移动时音乐改变进展Listener();方法也被调用,这在播放音乐时会造成障碍,所以我想要那个changeListener();只有当我用游标移动JSlider的nob时才应该调用该方法。请告诉我们该怎么做。

import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;




public class A implements ChangeListener {

    Clip clip;

    public A() throws Exception {

         JFrame f = new JFrame();
         f.setSize(800,400);
         f.setVisible(true);
         f.setLayout(null);
         URL url = this.getClass().getClassLoader().getResource("jal pari.wav");
         AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
         clip = AudioSystem.getClip();
         clip.open(audioIn);
         int x = (int)(clip.getMicrosecondLength()/1000000);
         JSlider s = new JSlider(JSlider.HORIZONTAL,0,x,0);
         s.addChangeListener(this);
         s.setBounds(50,50,800,100);
         f.add(s);
         clip.start();


         while( clip.getMicrosecondPosition()!=clip.getMicrosecondLength() ) {
             s.setValue((int)(clip.getMicrosecondPosition()/1000000));
         }
    }

    public static void main(String arg[]) throws Exception {
        new A();
    }


    public void stateChanged(ChangeEvent e) {
        JSlider js = (JSlider)e.getSource();
        int v = js.getValue();
        clip.setMicrosecondPosition(v*1000000);
    }


}

1 个答案:

答案 0 :(得分:1)

每当基础stateChanged发生更改时,都会引发BoundedRangeModel事件。这可能有多种原因。问题是,你不知道为什么,而且一般都不关心。

在您的情况下,您有两个(主要)情况可能会更改模型。 while-loop和用户。

您需要的是一些改变状态的方法,以便能够在某些情况下检测谁在进行更改或阻止更改通知。

在这个(简单)示例中,我使用简单的标志来指示更新发生的位置,并停止修改元素以更新模型,直到另一个完成。这可以在这里使用,因为我使用了Swing Timer来执行进度更新,这确保了"定时"更新和用户更新发生在同一线程的上下文中。这提供了一定程度的保护,因为TimerstateChanged方法运行时尝试更改UI的状态是不可能的。

这也意味着当从{"时间进度"中提出stateChanged事件时代码,我们的stateChanged处理程序会忽略它,因此它不会弄乱Clip的当前位置

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class MusicPlayer {

    public static void main(String[] args) {
        new MusicPlayer();
    }

    public MusicPlayer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JSlider slider;
        private Clip clip;
        private Timer updateTimer;
        private boolean timerUpdate = false;
        private boolean userUpdate = false;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            slider = new JSlider();
            slider.setMinorTickSpacing(5);
            slider.setMajorTickSpacing(10);
            slider.setPaintTicks(true);
            slider.setValue(0);
            add(slider);

            updateTimer = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (clip != null) {
                        if (!userUpdate) {
                            timerUpdate = true;
                            try {
                                long length = TimeUnit.NANOSECONDS.convert(clip.getMicrosecondLength(), TimeUnit.SECONDS);
                                long time = TimeUnit.NANOSECONDS.convert(clip.getMicrosecondPosition(), TimeUnit.SECONDS);
                                int progress = (int) Math.round(((double) time / (double) length) * 100d);
                                slider.setValue(progress);
                            } finally {
                                timerUpdate = false;
                            }
                        }
                    }
                }
            });
            updateTimer.start();

            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    if (!timerUpdate && !userUpdate) {
                        userUpdate = true;
                        try {
                            long length = clip.getMicrosecondLength();
                            int progress = slider.getValue();
                            long time = (long) (length * (progress / 100d));
                            clip.setMicrosecondPosition(time);
                        } finally {
                            userUpdate = false;
                        }
                    }
                }
            });

            try {
                File source = new File("\\...\\Kalimba.wav");
                AudioInputStream audioIn = AudioSystem.getAudioInputStream(source);
                clip = AudioSystem.getClip();
                clip.open(audioIn);
                clip.start();
            } catch (UnsupportedAudioFileException | IOException | LineUnavailableException exp) {
                exp.printStackTrace();
            }
        }
    }

}