我编写了一个小程序作为初学者练习,仅用两个JSlider将Celcius转换为Fahrenheit,反之亦然。我让两个JSlider互相监听,目的是每当我移动一个滑块时,无论是Celcius滑块(在窗口中的上部)还是Fahrenheit滑块(在下部),另一个滑块应自动移动到正确的位置但是,该程序存在我无法理解的错误。当我运行它时,它可以工作,但是我在Celcius条“ Clabel”下方的Celcius度JLabel仅以0、5、10、15等来显示,以此类推。而且我的Fahrenheitbar仅跳9的距离,例如0、9、18、27等。为什么是这样?为什么两个杆都没有卡死而平稳移动?
这是我的代码:
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条下移动的每个摄氏度,例如0、1、2、3、4,依此类推(应如此)。但是,如果这样做,在移动华氏温度栏时,我当然会失去摄氏温度栏上的任何功能,因为我不再通过移动华氏度滑块设置的任何值来控制摄氏温度线。因此,我只停留在较高的JSlider能够控制较低的JSlider并显示值的每个变化(如20、21、22 C)上,或者两个JSlider互相侦听,但间隔为0,5,10 ,15 C等。
谁能告诉我为什么两个滑块互相听时我无法获得每个数字变化的平稳反馈?为什么只以5s或9s为步长变化?
最佳答案
正如您所发现的,您的问题是每个ChangeListener
都会更改另一个滑块的值。滑块C更改滑块F的值,滑块C的值更改滑块F的值。仅当每次更改都不会导致另一个滑块的位置发生变化时,这种相互递归才会结束,这发生在5(在C中)和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());
}
});
另外在您的
private boolean updateInProgress = false;
类中声明ThermoWindow
。