So, I have a strange problem:
I have a JSlider
and a JSpinner
, the Slider uses int values while the spinner accepts double values. Now I want to 'connect' them by using change listeners:
slider.addChangeListener(e -> spinner.setValue(slider.getValue()));
spinner.addChangeListener(e -> slider.setValue(((Double) spinner.getValue()).intValue()));
But for some weird reason I get a ClassCastException:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
at rt.Main.lambda$rotateTo$29(Main.java:318)
at javax.swing.JSpinner.fireStateChanged(JSpinner.java:458)
at javax.swing.JSpinner$ModelListener.stateChanged(JSpinner.java:386)
at javax.swing.AbstractSpinnerModel.fireStateChanged(AbstractSpinnerModel.java:119)
at javax.swing.SpinnerNumberModel.setValue(SpinnerNumberModel.java:447)
at javax.swing.JSpinner.setValue(JSpinner.java:354)
at rt.Main.lambda$rotateTo$28(Main.java:317)
at javax.swing.JSlider.fireStateChanged(JSlider.java:432)
at javax.swing.JSlider$ModelListener.stateChanged(JSlider.java:350)
at javax.swing.DefaultBoundedRangeModel.fireStateChanged(DefaultBoundedRangeModel.java:364)
at javax.swing.DefaultBoundedRangeModel.setRangeProperties(DefaultBoundedRangeModel.java:302)
at javax.swing.DefaultBoundedRangeModel.setValue(DefaultBoundedRangeModel.java:168)
at javax.swing.JSlider.setValue(JSlider.java:531)
at rt.Main.lambda$rotateTo$29(Main.java:318)
at javax.swing.JSpinner.fireStateChanged(JSpinner.java:458)
at javax.swing.JSpinner$ModelListener.stateChanged(JSpinner.java:386)
at javax.swing.AbstractSpinnerModel.fireStateChanged(AbstractSpinnerModel.java:119)
at javax.swing.SpinnerNumberModel.setValue(SpinnerNumberModel.java:447)
at javax.swing.JSpinner.setValue(JSpinner.java:354)
at javax.swing.plaf.basic.BasicSpinnerUI$ArrowButtonHandler.actionPerformed(BasicSpinnerUI.java:654)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.Component.processMouseEvent(Component.java:6539)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6304)
at java.awt.Container.processEvent(Container.java:2239)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2297)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
at java.awt.Container.dispatchEventImpl(Container.java:2283)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
I noticed the following:
Using System.out.println(spinner.getValue().getClass())
I get class java.lang.Double
.
I checked the parameters on the spinner.setValue()
method and it takes a primitive int
.
Using the code spinner.addChangeListener(e -> System.out.println(((Double) spinner.getValue()).intValue()));
does work without throwing an exception and prints an int.
I also tried different solutions like Math.round()
or (int) Double.doubleValue()
, until now nothing worked.
If anyone has an Idea why this happens please tell me!
Edit:
While trying around some more I found out that slider.setValue(((Number) spinner.getValue()).intValue())
does work, but I would still like to now why?
I checked the class returned again and it still is: java.lang.Double
!
Any help appreciated
The first listener
slider.addChangeListener(e -> spinner.setValue(slider.getValue()));
is setting the value of the spinner to an Integer
- slider.getValue()
returns an int
that is boxed since spinner.setValue()
requires an Object
.
Probably* you are using a SpinnerNumberModel
which accepts any Number
for its properties (see javadoc). Since the value of the spinner was changed (programmatically by first listener), its listener is also called, causing the exception since it now have an Integer
as value.
Simple test showing that the spinner gets an Integer
:
JSlider slider = new JSlider(0, 0, 9, 5);
JSpinner spinner = new JSpinner(new SpinnerNumberModel(5.0, 0.0, 9.0, 1.0));
slider.addChangeListener(e -> spinner.setValue(slider.getValue()));
spinner.addChangeListener(e -> slider.setValue(((Number) spinner.getValue()).intValue()));
JOptionPane.showMessageDialog(null, new Object[] { slider, spinner });
System.out.println(spinner.getValue().getClass());
move the slider and press OK
- it will set the spinner value to an Integer
.
* missing such minimal complete example in question
Correct solution, IMHO:
slider.addChangeListener(e -> spinner.setValue((double)slider.getValue()));
spinner.addChangeListener(e -> slider.setValue(((Number) spinner.getValue()).intValue()));
I left the cast to Number
as metallurg suggested since the model is designed to work with Number
.