Search code examples
javaswinguser-interfacestatic-methodssettext

Change JLabel value of void GUI constructor from external method


I am trying to create a method in order to change the value of a JLabel in my creatAndShowGUI() method. What I want to do is change the value of some JLabels after importing a file (according to the file information).

private static void createAndShowGUI(){
    // Create and set up window
    final JFrame frame = new JFrame("SongApp");


    // Display the window
    frame.setSize(400, 150);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Set flowlayout
    frame.getContentPane().setLayout(new FlowLayout());
    try{
        UIManager.setLookAndFeel(
                UIManager.getSystemLookAndFeelClassName());      
    } catch(Exception e){
        System.err.println("Cannot set look and feel: " + e);
    }

    JButton loadFile = new JButton("Choose a new file ...");
    JLabel songLength = new JLabel("0:00");
    JLabel songName = new JLabel("No song selected yet");

    loadFile.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){

            createFileChooser(frame);

        }
    });

    frame.getContentPane().add(loadFile);
    frame.getContentPane().add(songLength);
    frame.getContentPane().add(songName);
}

My method needs to be void since I call it later on in my main method in

    javax.swing.SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            createAndShowGUI();                
        }
    });

After this I created a method as following:

private static void changeWindowInformation(String filename, int time) {

    createAndShowGUI().songName.setText(filename);
    // code to check time of song and return it in format xx:xx
    createAndShoGUI().songLength.setText(time);

}

This method is called in a createFileChooser method which is called in the createAndShowGUI() method after clicking a JButton.

I get to see an error message: void cannot be dereferenced. I am pretty new in Java programming and don't really know what I am doing wrong. Should I place the creation of my frame somewhere else in my code (maybe under my main method?) or am I not accessing the JLabel in the correct way? I have tried to place the method call in my loadFile.addActionListener method and make it only return strings so I can access the JLabels in loadFile.addActionListener but I still get the same error message.

If you need any further information, just tell me.

Thanks already for your help!!


Solution

  • You should make your own Frame-class which inherits JFrame and add the changing labels as class members, because as gparyani already commented

    You can't access local variables declared in a method from another method.

    For example:

    public class MyFrame extends JFrame {
      private JLabel songName, songLength;
    
      public MyFrame() {
        super("SongApp");
        songLength = new JLabel("0:00");
        songName = new JLabel("No song selected yet");
        JButton loadFile = new JButton("Choose a new file ...");
    
        //other UI settings
    
        loadFile.addActionListener(new ActionListener(){
          public void actionPerformed(ActionEvent e){
            createFileChooser(this);
          }
        });
    
        getContentPane().add(loadFile);
        getContentPane().add(songLength);
        getContentPane().add(songName);
      }
    
      public void changeWindowInformation(String filename, int time) {
        this.songName.setText(filename);
        this.songLength.setText(yourFormattedTime); 
      }
    }
    

    Further you could pass the reference of this class to your createFileChooser()

    public void createFileChooser(MyFrame callingFrame) {
      //your filechooser logic
    
      callingFrame.changeWindowInformation(filename, time);
    }
    

    If createFileChooser() is a method of MyFrame, passing an instance of MyFrame is unnecessary, because changeWindowInformation and createFileChooser would be members of the same instance so they share the same class-members. In this case your code should be:

    public void createFileChooser() {
      //your filechooser logic
    
      changeWindowInformation(filename, time);
    }
    

    Using this, you can replace your whole createAndShowGUI()-call with this:

    javax.swing.SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            MyFrame frame = new MyFrame();
            frame.setVisible(true);               
        }
    });