mre
mre

Reputation: 44240

Strange Swing compile-time accessibility error

Here is the code -

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public final class SetLabelForDemo {
    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                createAndShowGUI();             
            }
        });
    }

    private static void createAndShowGUI(){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JLabeledButton("foo:")); // new JLabeledButton("foo:") is the problem
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private final class JLabeledButton extends JButton{
        public JLabeledButton(final String s){
            super();
            JLabel label = new JLabel(s);
            label.setLabelFor(this);
        }
    }
}

And here is the error message -

No enclosing instance of type SetLabelForDemo is accessible. Must qualify the allocation with an enclosing instance of type SetLabelForDemo (e.g. x.new A() where x is an instance of SetLabelForDemo).

I don't understand this error at all. To me, everything seems perfectly valid. Am I missing something?

Upvotes: 2

Views: 195

Answers (4)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285401

I know you've accepted an answer, but the other way to solve it is to instantiate the inner class on an instance of the outer class. e.g.,

private static void createAndShowGUI() {
   final JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.getContentPane().add(
         new SetLabelForDemo().new JLabeledButton("foo:"));
   frame.pack();
   frame.setLocationRelativeTo(null);
   frame.setVisible(true);
}

This is a funny syntax, but it works. And this has nothing to do with Swing and all to do with use of inner classes inside of a static context.

Upvotes: 3

JB Nizet
JB Nizet

Reputation: 691685

The JLabeledButton class should be static. Else, it can only be instantiated as part of an enclosing SetLabelForDemo instance. A non static inner class must always have an implicit reference to its enclosing instance.

Upvotes: 3

Prince John Wesley
Prince John Wesley

Reputation: 63688

Mark JLabeledButton as static class.

Upvotes: 2

Howard
Howard

Reputation: 39197

You'll have to declare your class JLabeledButton static since you instantiate it within a static context:

private static final class JLabeledButton extends JButton {
    ...
}

Because your method createAndShowGUI is static the compiler does not know for which instance of SetLabelForDemo you are creating the enclosed class.

Upvotes: 3

Related Questions