-1

I have designed this method to display a window with a slider which value I need to return. Can you please tell me how I can retrieve the JSlider value a currently I am getting the error: "local variables referenced from an inner class must be final or effectively final"?

private static int displayFontPanel(JFrame w){
    JFrame window = new JFrame("Font Settings");
    window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    int fontSize = 14;
    window.setSize(400, 200);
    window.setLocationRelativeTo(w);
    JSlider fntSize = new JSlider(8,40,20);
    fntSize.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent evt) {
            fontSize = ((JSlider)evt.getSource()).getValue();
        }
    });
    fntSize.setLabelTable( fntSize.createStandardLabels(8) );
    fntSize.setPaintLabels(true);
    panel.add(fntSize, BorderLayout.CENTER);
    window.setContentPane(panel);
    window.setVisible(true);
    return fontSize;
} 
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
florin.iliescu
  • 302
  • 4
  • 10

3 Answers3

0

Change the method signature to

public void stateChanged(final ChangeEvent evt) {

After that you will be able to do

((JSlider) evt.getSource()).getValue()

This answer explains better than I can why the variable needs to be final: https://stackoverflow.com/a/4732617/3061857

Community
  • 1
  • 1
nbokmans
  • 5,492
  • 4
  • 35
  • 59
  • I did the change, but this did not solved anything. How can I get the getValue out of stateChanged method? This is my problem: error: local variables referenced from an inner class must be final or effectively final fontSize = ((JSlider)evt.getSource()).getValue(); – florin.iliescu Mar 02 '17 at 09:58
0

Does the code error refer really to slider, not fontSize? If latter is the case, then you have to "cheat" the system a little. Variables referenced in a closure have to be final, that is - unchanged in the following code.

But if you cheat a little, and declare fontSize as an array (final int[] fontSize = new int[1]) and modify its content, everything should work, like so:

fntSize.addChangeListener(new ChangeListener()   {
    public void stateChanged(ChangeEvent evt) {
        fontSize[0] = ((JSlider)evt.getSource()).getValue();
       }
    });
lukeg
  • 4,189
  • 3
  • 19
  • 40
  • Yes, it did the trick. Thank you! But why does it have to be so complicated?! Is not there another solution to manage this issue? – florin.iliescu Mar 02 '17 at 10:47
0

I would use AtomicInteger instead of int:

    private static int displayFontPanel(JFrame w){
      JFrame window = new JFrame("Font Settings");
      window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      JPanel panel = new JPanel();
      panel.setLayout(new BorderLayout());
      final AtomicInteger fontSize = new AtomicInteger(14);
      window.setSize(400, 200);
      window.setLocationRelativeTo(w);
      JSlider fntSize = new JSlider(8,40,20);
      fntSize.addChangeListener(new ChangeListener()   {
        public void stateChanged(ChangeEvent evt) {
            fontSize.set(((JSlider)evt.getSource()).getValue());
        }
      });
      fntSize.setLabelTable( fntSize.createStandardLabels(8) );
      fntSize.setPaintLabels(true);
      panel.add(fntSize, BorderLayout.CENTER);
      window.setContentPane(panel);
      window.setVisible(true);
      return fontSize.get();
}
SaWo
  • 1,515
  • 2
  • 14
  • 32