Search code examples
javaswingstaticjlabelprivate-members

Unable to access jlabel across the program


I am new to Java, hence this basic question.

I am having trouble in accessing a field (jlabel in this case) throughout the program. My code is as follows :

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class accessvariable {

    public static void main(String[] args) {

        //basic setup of display frame
        JFrame frame=new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);
        JPanel panel=new JPanel();

        //text field to take user input
        JTextField txt= new JTextField(10);

        //adding action listener for text field
        txt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (true) { //if condition not checking anything here, just to make it enter the loop
                    JLabel j =new JLabel("Access successful"); //a jlabel created inside this 
                    System.out.println("inside j : "+j.getText()); //statement to check whether jlabel is accessible from here
                }
            }
        });

        System.out.println("outside j : "+j.getText()); //statement to check whether jlabel is accessible from here

        //basic setup for final display
        panel.add(txt);
        frame.getContentPane().add(panel);
        frame.setVisible(true);
    }
}

The error is on this line:

System.out.println("outside j : "+j.getText());

If I comment out this line, it works fine. The inside j is displayed correctly. But if I don't comment it, I am getting this error:

Exception in thread "Exception in thread "main" java.lang.Error: Unresolved compilation problem: j cannot be resolved"

To correct this, I have made j an instance variable as follows:

private JLabel j; 

However the above is generating a new error:

Cannot make a static reference to the non-static field j

I understand that the problem is with this single line:

System.out.println("outside j : "+j.getText());

How can I fix the above problem so that if it works correctly, the output when I enter some text in the text field should be as follows:

inside j : Access successful
outside j : Access successful

Solution

  • Wait. Stop. Start over.

    Your program is nothing more than a static main method, which is fine for "Hello World" type programs, but if you are desiring to create anything more powerful, you will want to, no need to learn about Object-Oriented concepts and how to apply them in Java programs. For instance, for a start for this project you should create at least one class that has non-static fields and methods, including a field for your JLabel (by which you would allow non-static methods of your class access to this field), and you should build your GUI, meaning add components to the containers, outside of the main method, and more like in some non-static init() method or constructor. The main method should only be for creating your objects and setting them into action and little else. But again most importantly, learn OOP concepts and how they relate to the Java programming language. A decent book for this is Bruce Eckel's "Thinking in Java".

    Another concept to hit hard now is scope including variable scope. If you have a variable, here the JLabel variable, j, buried and declared not just inside of a method, but in a method that is buried inside of an anonymous inner ActionListener class, it will be almost impossible for other class code to interact with this variable. If it is an instance field, then it is visible throughout all the non-static parts of the class that holds it.

    For example:

    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class AccessVariable extends JPanel {
        private static final int PREF_W = 400;
        private static final int PREF_H = PREF_W;
        private JLabel myLabel = new JLabel();
        private JTextField textField = new JTextField(10);
    
        public AccessVariable() {
            add(textField);
            add(myLabel);
    
            textField.addActionListener(new MyListener());
        }
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    
        private class MyListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                String text = textField.getText();
                myLabel.setText("Text is: " + text);
    
                textField.requestFocusInWindow();
                textField.selectAll();
            }
        }
    
        private static void createAndShowGui() {
            AccessVariable mainPanel = new AccessVariable();
    
            JFrame frame = new JFrame("Access Variable");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGui();
                }
            });
        }
    }