Basically, what you can do is insert a "forced delay" between the time the stateChanged
event is raised and the time that the textField
is updated.
This basically means we are waiting for a fixed period of time between when the stateChanged
method was last called BEFORE we try and update the textField
.
Because we don't want to block the Event Dispatching Thread, because it would stop any new events from being processed, I've used a javax.swing.Timer
.
Basically, whenever the stateChanged
method is called, I restart the timer. Once the events stop, the timer is allowed to complete and triggers a actionPerformed
event, which allows us to update the textField
...easy ;)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestSlider01 {
public static void main(String[] args) {
new TestSlider01();
}
public TestSlider01() {
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 JTextField textField;
private Timer slideTimer;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
textField = new JTextField(20);
slider = new JSlider(JSlider.HORIZONTAL, 0, 30, 2);
slider.setFont(new Font("Dialog", Font.BOLD, 10));
slider.setMinorTickSpacing(1);
slider.setMajorTickSpacing(2);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
// textField.setText(String.valueOf(slider.getValue()));
slideTimer.restart();
}
});
slideTimer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
textField.setText(String.valueOf(slider.getValue()));
}
});
slideTimer.setRepeats(false);
add(slider, gbc);
add(textField, gbc);
}
}
}
Now, I've deliberately used a largish value for the delay, you may wish to play with it...
Also, setBounds
is a very bad idea. I would invest the time into learning the layout manager API, it will save you a lot of heart-ache in the long run ;)