2

Background

On following screenshot, the user should be able to change the image by clicking on one of the radio buttons:

screenshot

When a radio button is clicked the picture should change to a different one . I have put all images into an array.

Problem

When compiling code I have tried so far (see source below) the compiler gives following error:

Error: local variable imagesLabel is accessed from within inner class; needs to be declared final

And once I add final before respective variable, I got following error when compiling:

Error: <identifier> expected

Java Code (after adding the final)

Icon[] images = new Icon[3];

// Get the images and store them in the images array.  These images 
// were manually resized to be similar in size prior to writing the
// program.
images[0] = new ImageIcon("/Users/grimygod/Desktop/negativeFilterExample.png");
images[1] = new ImageIcon("/Users/grimygod/Desktop/reflect.png");
images[2] = new ImageIcon("/Users/grimygod/Desktop/colorSubtraction.png");

// The images will be displayed as the image on a JLabel without text
JLabel imagesLabel = new JLabel();

// Set the initial image to be the negative filter, and add it to the panel,
// since the radio button for the negative filter is initially selected.
imagesLabel.setIcon(images[0]);
iconPanel.add(imagesLabel);
radioButtonPanel.add(iconPanel);

// Creation of "Select An Image & Apply Filter!" button
JButton selectButton = new JButton("Select An Image & Apply Filter!");
submitButtonPanel.add(selectButton);
radioButtonPanel.add(submitButtonPanel);

// Makes the whole window visible
testFrame.setVisible(true); 

// First button is selected when program is ran
button1.setSelected(true);

button1.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        final imagesLabel.setIcon(images[2]);   //  <<<<< ERROR in this line 
   }
});
hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • 1
    It's the variable imagesLabel that must be declared final: `final JLabel imagesLabel = new JLabel();`. But you shouldn't have this error unless you use Java 7 or before. Why are you using such an old version of Java? – JB Nizet Dec 02 '19 at 22:09
  • It's for my class at school, my teacher told us what to download. – sinafarheidar12 Dec 02 '19 at 22:39

2 Answers2

0

You can do any of the following to resolve the issue:

A. Declare imagesLabel as final

final JLabel imagesLabel = new JLabel();

B. Declare imagesLabel as an instance variable i.e. outside the method. In other words, declare it in the class itself.

Make sure to remove final from final imagesLabel.setIcon(images[2]); i.e. it should be simply imagesLabel.setIcon(images[2]);

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • I just tried that and it's still giving me an error that says "Error: local variable images is accessed from within inner class; needs to be declared final" – sinafarheidar12 Dec 02 '19 at 22:40
  • 1
    @sinafarheidar12 so do the same thing with images. Same error, same fix. – JB Nizet Dec 02 '19 at 22:41
  • 1
    Okay, but now I'm getting an error saying "Error: non-static variable imagesLabel cannot be referenced from a static context". I tried writing it in public void main(String[] args), but it didn't work either – sinafarheidar12 Dec 02 '19 at 22:50
  • That fixed it! Thanks for helping me out guys! – sinafarheidar12 Dec 02 '19 at 22:59
0

Issue A

You are defining an anonymous inner class of type ActionListener when adding the listener, see (1) in code below. Then you try to access the variable imagesLabel which is declared outside (of the inner class), see (2) in code below. Since this variable is declared non-final, you cannot use it within an anonymous inner class like this.

► Thus compiling failed with message:

Error: local variable imagesLabel is accessed from within inner class; needs to be declared final

Code in state A (before final was added):

button1.addActionListener(new ActionListener() { // (1)
    @Override
    public void actionPerformed(ActionEvent e) {
        imagesLabel.setIcon(images[1]);   //  (2) <<<<< ERROR in this line 
   }
});

Issue B

Trying to solve it you followed the instruction of the message and would like to "declare" the variable imagesLabel as final directly in this line - marked (3) in code below.

But the line (3) is not the location of declaration of variable imagesLabel, rather than a method call on this instance variable.

The compiler reads the source code line beginning with final and expects an identifier hereafter, but there was a method call.

► Thus compiling failed with message:

Error: <identifier> expected

Code in state B (after final was added):

button1.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        final imagesLabel.setIcon(images[1]);   //  (3) <<<<< ERROR in this line 
   }
});

⚠ NOTE: same compilation error and fix (as commented by JB Nizet) applies to variable images which is used as argument in the same line (3) above.

Solution

You have to use the modifier final where the variable imagesLabel (as well as images array) is declared. Then you can access it inside the inner class like first in code state A:

final Icon[] images = new Icon[3]; // <<< here is the other declaration

/* ... lines of code left out for clarity  ... */

// The images will be displayed as the image on a JLabel without text
final JLabel imagesLabel = new JLabel(); // <<< here is the declaration

/* ... lines of code left out for clarity  ... */

button1.addActionListener(new ActionListener() { // (1) inner class
    @Override
    public void actionPerformed(ActionEvent e) {
        imagesLabel.setIcon(images[1]);   //  (2) <<<<< now you can use the final declared variable imagesLabel
   }
});

See also

hc_dev
  • 8,389
  • 1
  • 26
  • 38