JSlider не обновляется должным образом от событий мыши

У меня есть апплет, который выбирает аудиофайл из JFileChooser. Два JSlider создаются или обновляются в соответствии с длиной клипа и называются «точка A» и «точка B». Нажимается кнопка J, после чего файл воспроизводится до точки А. Когда он достигает точки А, клип начинает зацикливать звук из точки А в точку Б с плавным переходом.

Проблема в том, что я должен убедиться, что точка А никогда не выходит за пределы точки Б по очевидным причинам, но мой метод для этого не работает.

Добавление прослушивателя изменений, который обновляется, когда исходный JSlider обновляется или не обновляется, - это две вещи, которые я пробовал. Для !source.getValueIsAdjusting() он работает для использования клавиш со стрелками, но не для мыши, а для source.getValueIsAdjusting() он работает с задержкой: кажется, что он либо сравнивает, либо сбрасывает значения с опозданием.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SliderExample extends JApplet{

    private MyPanel panel;
    private final Random rand = new Random();


    public SliderExample() {
        panel = new MyPanel();
        add(panel);
    }

    private class MyPanel extends JPanel implements 
    ActionListener{

        private JSlider sliderA, sliderB;
        private final Timer t = new Timer(20, this);

        public MyPanel()
        {
            super(false);
            sliderA = new JSlider(JSlider.HORIZONTAL, 0, 20, 5);
            sliderB = new JSlider(JSlider.HORIZONTAL, 0, 20, 15);
            sliderA.setBorder(BorderFactory.createTitledBorder("Point A"));
            sliderB.setBorder(BorderFactory.createTitledBorder("Point B"));
            sliderA.setMajorTickSpacing(5);
            sliderB.setMajorTickSpacing(5);
            sliderA.setMinorTickSpacing(1);
            sliderB.setMinorTickSpacing(1);
            sliderA.setPaintTicks(true);
            sliderB.setPaintTicks(true);
            sliderA.setPaintLabels(true);
            sliderB.setPaintLabels(true);
            sliderA.addChangeListener(new SliderHandler());
            sliderB.addChangeListener(new SliderHandler());

            add(sliderA);
            add(sliderB);

            t.start();
        }

        @Override
        public void actionPerformed(ActionEvent e) {

//          uncomment these to see that the slider set value does work
//          sliderA.setValue(rand.nextInt(sliderA.getMaximum()));  
//          sliderB.setValue(rand.nextInt(sliderB.getMaximum()));


            int A = sliderA.getValue();
            int B = sliderB.getValue();
            if (A > B)
            {
                System.out.println("ERROR: slider A is: " + A + " and slider B is : " + B);
                sliderA.setValue(B);
            }
        }

        private class SliderHandler implements ChangeListener
        {
            private SliderHandler() 
            {
            }

            public void stateChanged(ChangeEvent e) 
            {
                JSlider source = (JSlider)e.getSource();
                if (!source.getValueIsAdjusting())
                {
                    if (source == sliderA) 
                    {
                        if (source.getValue() > sliderB.getValue())
                        {
                            source.setValue(sliderB.getValue());
                        }

                    }
                    else if (source == sliderB)
                    {
                        if (source.getValue() < sliderA.getValue())
                        {
                            source.setValue(sliderA.getValue());
                        }
                    }
                }
            }
        }   
    }
}

person michaelsnowden    schedule 12.11.2013    source источник
comment
Основная проблема в том, что getValueIsAdjusting мешает обновлениям. Если вы удалите это, вы сможете выполнять непрерывную проверку каждый раз при изменении состояния. Я также думаю, что вы сравниваете неправильно. if a > b then b = a, а не a = b, но это только мои ожидания...   -  person MadProgrammer    schedule 12.11.2013
comment
Смотрите редактировать, чтобы ответить. Я думаю, что сначала ответил на неправильный вопрос, но теперь я ответил на него правильно. Вы забыли вызвать setSnapToTicks(true) на своих JSliders.   -  person Hovercraft Full Of Eels    schedule 12.11.2013


Ответы (1)


Кажется, это работает нормально для меня. Я изменил свои ползунки на + 1 или - 1 из значения, от которого я пытаюсь уйти. Например:

import javax.swing.*;
import javax.swing.event.*;

@SuppressWarnings("serial")
public class SliderExample2 extends JPanel {
   private JSlider sliderA = new JSlider(JSlider.HORIZONTAL, 0, 20, 5);
   private JSlider sliderB = new JSlider(JSlider.HORIZONTAL, 0, 20, 15);
   private JSlider[] sliders = {sliderA, sliderB};
   private String[] titles = {"Point A", "Point B"};

   private ChangeListener[] changeListeners = {new ChangeListenerA(), 
           new ChangeListenerB()};

   public SliderExample2() {
      for (int i = 0; i < sliders.length; i++) {
         sliders[i].setBorder(BorderFactory.createTitledBorder(titles[i]));
         sliders[i].setMajorTickSpacing(5);
         sliders[i].setMinorTickSpacing(1);
         sliders[i].setPaintTicks(true);
         sliders[i].setPaintLabels(true);             
         sliders[i].addChangeListener(changeListeners[i]);             
         add(sliders[i]);             
      }
   }

   private class ChangeListenerA implements ChangeListener {
      @Override
      public void stateChanged(ChangeEvent cEvt) {
         if (sliderA.getValue() >= sliderB.getValue()) {
            sliderB.setValue(sliderA.getValue() + 1);
         }
      }
   }

   private class ChangeListenerB implements ChangeListener {
      @Override
      public void stateChanged(ChangeEvent cEvt) {
         if (sliderA.getValue() >= sliderB.getValue()) {
            sliderA.setValue(sliderB.getValue() - 1);
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("SliderExample2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SliderExample2());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Изменить

О, я вижу вашу цель и проблему - вы хотите ограничить диапазон перемещаемого ползунка. Вы забыли установить setSnapToTicks(true):

import javax.swing.*;
import javax.swing.event.*;

@SuppressWarnings("serial")
public class SliderExample3 extends JPanel {
   private JSlider sliderA = new JSlider(JSlider.HORIZONTAL, 0, 20, 5);
   private JSlider sliderB = new JSlider(JSlider.HORIZONTAL, 0, 20, 15);
   private JSlider[] sliders = {sliderA, sliderB};
   private String[] titles = {"Point A", "Point B"};

   private ChangeListener[] changeListeners = {new ChangeListenerA(), 
           new ChangeListenerB()};

   public SliderExample3() {
      for (int i = 0; i < sliders.length; i++) {
         sliders[i].setBorder(BorderFactory.createTitledBorder(titles[i]));
         sliders[i].setMajorTickSpacing(5);
         sliders[i].setMinorTickSpacing(1);
         sliders[i].setPaintTicks(true);
         sliders[i].setPaintLabels(true);
         sliders[i].setSnapToTicks(true);
         sliders[i].addChangeListener(changeListeners[i]);             
         add(sliders[i]);             
      }
   }

   private class ChangeListenerA implements ChangeListener {
      @Override
      public void stateChanged(ChangeEvent cEvt) {
         if (sliderA.getValue() >= sliderB.getValue()) {
            sliderA.setValue(sliderB.getValue());
         }
      }
   }

   private class ChangeListenerB implements ChangeListener {
      @Override
      public void stateChanged(ChangeEvent cEvt) {
         if (sliderA.getValue() >= sliderB.getValue()) {
            sliderB.setValue(sliderA.getValue());
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("SliderExample3");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SliderExample3());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
person Hovercraft Full Of Eels    schedule 12.11.2013
comment
Ад да! Это то, о чем я говорю! - person michaelsnowden; 12.11.2013