2016-04-11 19 views
2

Ich habe ein kleines Programm als Anfängerübung geschrieben, um Celcius einfach mit zwei JSlidern in Fahrenheit und umgekehrt umzuwandeln. Ich habe die beiden JSliders aufeinander hören lassen, und das Ziel ist, dass, wenn ich einen Schieberegler bewege, entweder der Celzius (der obere im Fenster) oder der Fahrenheit (unten), der andere sich automatisch an die richtige Stelle bewegen soll Allerdings hat das Programm einen Fehler, den ich nicht verstehen kann. Wenn ich es laufe, funktioniert es, aber mein Celcius-Grad JLabel unterhalb der Celcius-Leiste "Cabel" wird nur in Takten von 0,5,10,15 gezeigt ... und so weiter, wenn ich seinen Schieberegler bewege. Und meine Fahrenheitbar springt nur in Abständen von 9, wie 0,9,18,27 so weiter. Warum ist das? Warum bewegen sich beide Balken nicht ohne Stottern?Zwei JSlider synchronisieren

Hier ist mein Code:

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

Wenn ich die folgende Zeile in der zweiten Change

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

dann kommentieren Sie die obere Celcius bar bewegt jeden einzelnen Celcius Grad zeigt unter dem celcius bar bewegt , wie 0,1,2,3,4 und so weiter (wie es sollte). Aber wenn ich das tue, verliere ich jede Funktionalität auf der Celcius-Leiste, wenn ich den Fahrenheit-Balken verschiebe, da ich nicht mehr die Celcius-Leiste mit dem Wert steuere, den ich durch Bewegen des Fahrenheit-Reglers eingestellt habe. So bleibe ich entweder mit dem oberen JSlider stecken, der den unteren steuern kann, und zeige jede einzelne Wertänderung (zB 20,21,22 C) ODER beide JSliders hören sich gegenseitig zu, aber nur in Intervallen von 0,5,10 , 15 C und so weiter.

Kann mir jemand sagen, warum ich keine reibungslose Rückmeldung von jeder einzelnen Ziffer Änderung bekommen kann, wenn beide Schieberegler aufeinander hören? Warum ändert es sich nur in Schritten von 5s oder 9s?

Antwort

4

Ihr Problem, wie Sie festgestellt haben, ist jeder ChangeListener Ändern des Werts des anderen Sliders. Schieberegler C ändert den Wert von Schieberegler F, der den Wert von Schieberegler C ändert, wodurch der Wert von Schieberegler F geändert wird. Diese gegenseitige Rekursion endet nur dann, wenn jede Änderung keine Änderung der Position des anderen Schiebers bewirkt, was bei den 5er (in C) und 9er (in F) geschieht.

Sie benötigen Code wie folgt aus:

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 erklären private boolean updateInProgress = false; in Ihrer ThermoWindow Klasse.

0

Das Problem ist, dass jedes Mal, wenn Sie einen Wert in einem der Wert der anderen Änderungen festlegen und dies auch seinen Rückruf auslöst. Da Sie die Werte abrunden, beginnend bei 0 und bis Sie den Celsius-Cursor auf 5 bewegen, bleibt der Fahrenheit-Wert bei 32 und ähnlich auf der anderen Seite.