2016-04-11 5 views
2

Я написал небольшую программу в качестве упражнения для начинающих, чтобы просто преобразовать Celcius в Fahrenheit и наоборот с двумя JSliders. У меня есть два JSliders, которые слушают друг друга, и цель состоит в том, что всякий раз, когда я перемещаю один слайдер, либо Celcius (верхний в окне), либо Fahrenheit (нижний), другой должен автоматически перемещаться в нужное место однако в программе есть ошибка, которую я не могу понять. Когда я запускаю его, он работает, но мой уровень Celcius JLabel под маркой Celcius «Clabel» показан только в показателях 0,5,10,15 .. и т. Д., Когда я перемещаю его слайдер. И мой Фаренгейтбар прыгает только на расстояние 9, например 0,9,18,27 и так далее. Почему это? Почему обе полосы не будут плавно двигаться без заикания?Синхронизация двух JSliders

Вот мой код:

import javax.swing.*; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 
import java.awt.*; 


public class ThermoWindow extends JFrame { 

    private JSlider C, F; 
    private JPanel panel, labelpanel; 
    private JLabel Flabel, Clabel; 

    public ThermoWindow() { 
     super("Thermometer Converter"); 
     panel = new JPanel(new BorderLayout()); 
     labelpanel = new JPanel(new BorderLayout()); 
     C = new JSlider(JSlider.HORIZONTAL,-100,100,0); 
     C.setMajorTickSpacing(10); 
     C.setMinorTickSpacing(1); 
     C.setPaintTicks(true); 
     C.setPaintLabels(true); 
     F = new JSlider(JSlider.HORIZONTAL,-100,100,toFahrenheit(0)); 
     F.setMajorTickSpacing(10); 
     F.setMinorTickSpacing(1); 
     F.setPaintTicks(true); 
     F.setPaintLabels(true); 

     Clabel = new JLabel(" C°: " + 0); 
     Flabel = new JLabel(" F°: " + toFahrenheit(0)); 

     C.addChangeListener(new ChangeListener() { 
      @Override 
      public void stateChanged(ChangeEvent e) { 
       F.setValue(toFahrenheit(C.getValue())); 
       Clabel.setText(" C°: " + C.getValue()); 
      } 
     }); 

     F.addChangeListener(new ChangeListener() { 
      @Override 
      public void stateChanged(ChangeEvent e) { 
       C.setValue(toCelcius(F.getValue())); 
       Flabel.setText(" F°: " + F.getValue()); 
      } 
     }); 

     panel.add(C, BorderLayout.NORTH); 
     panel.add(F, BorderLayout.SOUTH); 
     labelpanel.add(Clabel, BorderLayout.NORTH); 
     labelpanel.add(Flabel, BorderLayout.SOUTH); 
     panel.add(labelpanel); 

     add(panel); 
     setBounds(900,200,900,200); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     setResizable(false); 
     setVisible(true); 
    } 

    public int toFahrenheit(int temp){ 

     temp = (int)(temp/(5/(double)9))+32; 

     return temp; 
    } 

    public int toCelcius(int temp){ 

     temp = (int)((temp-32)*(5/(double)9)); 

     return temp; 
    } 

} 

    public class myThermometer { 
     public static void main (String[] args){ 
      new ThermoWindow(); 
     } 
    } 

Если я закомментируйте следующую строку во втором ChangeListener

C.setValue(toCelcius(F.getValue())); 

затем переместив верхнюю планку Celcius показывает каждую степень Celcius перемещается под бар Celcius , например 0,1,2,3,4 и т. д. (как и следовало бы). Но если я это сделаю, я потеряю любую функциональность на панели Celcius при перемещении бара Fahrenheit, конечно, потому что я больше не контролирую панель Celcius с любым значением, установленным перемещением ползунка Fahrenheit. Поэтому я застрял в том, что только верхний JSlider может контролировать нижний и показывать каждое изменение значения (например, 20,21,22 C), либо оба JSliders прослушивают друг друга, но только в промежутках 0,5,10 , 15 C и т. Д.

Может ли кто-нибудь сказать мне, почему я не могу получить гладкую обратную связь от каждой отдельной цифры, когда оба слайдера слушают друг друга? Почему это происходит только с шагом 5 или 9?

ответ

4

Ваша проблема, как вы обнаружили, - это каждый ChangeListener, изменяющий значение другого слайдера. Ползунок C изменяет значение ползунка F, которое изменяет значение ползунка C, которое изменяет значение ползунка F. Эта взаимная рекурсия заканчивается только тогда, когда каждое изменение не вызывает изменения в позиции другого ползунка, которое происходит на 5 (в С) и 9 (в F).

Вам нужно код вроде следующего:

C.addChangeListener(new ChangeListener() { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
      if (!updateInProgress) { 
       updateInProgress = true; 
       F.setValue(toFahrenheit(C.getValue())); 
       updateInProgress = false; 
      } 
      Clabel.setText(" C°: " + C.getValue()); 
     } 
    }); 

    F.addChangeListener(new ChangeListener() { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
      if (!updateInProgress) { 
       updateInProgress = true; 
       C.setValue(toCelcius(F.getValue())); 
       updateInProgress = false; 
      } 
      Flabel.setText(" F°: " + F.getValue()); 
     } 
    }); 

Plus объявить private boolean updateInProgress = false; в вашем ThermoWindow классе.

0

Проблема в том, что каждый раз, когда вы устанавливаете значение в единицу, значение других изменений и это также вызывает его обратный вызов. Поскольку вы округляете значения, начиная с 0 и до тех пор, пока вы не сдвинете курсор Цельсия до 5, значение Фаренгейта застряло до 32, и похоже на другой стороне.

Смежные вопросы