Search code examples
javaswingjtextfieldaccessor

Java JTextField information access from another class


I am using a gui with JTextFields to collect some information and then a JButton that takes that infomration and writes it to a file, sets the gui visibility to false, and then uses Runnable to create an instance of another JFrame from a different class to display a slideshow.

I would like to access some of the information for the JTextFields from the new JFrame slideshow. I have tried creating an object of the previous class with accessor methods, but the values keep coming back null (I know that I have done this correctly).

I'm worried that when the accessor methods go to check what the variables equal the JTextFields appear null to the new JFrame.

Below is the sscce that shows this problem.

package accessmain;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class AccessMain extends JFrame implements ActionListener 
{
    private static final int FRAMEWIDTH = 800;
    private static final int FRAMEHEIGHT = 300;

    private JPanel mainPanel;

    private PrintWriter outputStream = null;

    private JTextField subjectNumberText;

    private String subjectNumberString;

    public static void main(String[] args) 
    {
        AccessMain gui = new AccessMain();
        gui.setVisible(true); 
    }

    public AccessMain()
    {
        super("Self Paced Slideshow");
        setSize(FRAMEWIDTH, FRAMEHEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        //Begin Main Content Panel
        mainPanel = new JPanel();
        mainPanel.setBorder(new EmptyBorder(0,10,0,10));        
        mainPanel.setLayout(new GridLayout(7, 2));
        mainPanel.setBackground(Color.WHITE);
        add(mainPanel, BorderLayout.CENTER);

        mainPanel.add(new JLabel("Subject Number: "));
        subjectNumberText = new JTextField(30);
        mainPanel.add(subjectNumberText);

        mainPanel.add(new JLabel(""));
        JButton launch = new JButton("Begin Slideshow");
        launch.addActionListener(this);
        mainPanel.add(launch);
        //End Main Content Panel
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        String actionCommand = e.getActionCommand();

        if(actionCommand.equals("Begin Slideshow"))
        {
            subjectNumberString = subjectNumberText.getText();
            if(!(subjectNumberString.equals(""))) 
            {
                System.out.println(getSubjectNumber());
                this.setVisible(false);
                writeFile();
                outputStream.println("Subject Number:\t" + subjectNumberString);
                outputStream.close();
                SwingUtilities.invokeLater(new Runnable() 
                {
                    @Override
                    public void run() 
                    {
                        AccessClass testClass = new AccessClass();
                        testClass.setVisible(true);
                    }
                });      
            }
            else
            {
                //Add warning dialogue here later
            }
        }
    }

    private void writeFile()
    {
        try
        {
            outputStream = new PrintWriter(new FileOutputStream(subjectNumberString + ".txt", false));
        }
        catch(FileNotFoundException e)
        {
            System.out.println("Cannot find file " + subjectNumberString + ".txt or it could not be opened.");
            System.exit(0);
        }
    }

    public String getSubjectNumber()
    {
        return subjectNumberString;
    }
}

And then creating a barebones class to show the loss of data:

package accessmain;

import javax.swing.*;
import java.awt.*;

public class AccessClass extends JFrame
{
    AccessMain experiment = new AccessMain();
    String subjectNumber = experiment.getSubjectNumber();

    public AccessClass()
    {
        System.out.println(subjectNumber);  
    }
}

Hardcoding the accessor method with "test" like this:

public String getSubjectNumber()
{
    return "test";
}

Running this method as below in the new JFrame:

SelfPaceMain experiment = new SelfPaceMain();
private String subjectNumber = experiment.getSubjectNumber();
System.out.println(subjectNumber);

Does cause the system to print "test". So the accessor methods seem to be working. However, trying to access the values from the JTextFields doesn't seem to work.

I would read the information from the file I create, but without being able to pass the subjectNumber (which is used as the name of the file), I can't tell the new class what file to open.

Is there a good way to pass data from JTextFields to other classes?


Solution

  • pass the argument 'AccessMain' or 'JTextField' to the second class:

    SwingUtilities.invokeLater(new Runnable() 
    {
        @Override
        public void run() 
        {
            AccessClass testClass = new AccessClass(AccessMain.this); //fixed this
            testClass.setVisible(true);
        }
    });   
    

    Then reading the value of 'subjectNumber'(JTextField value) from the 'AccessMain' or 'JTextField' in the second class:

    public class AccessClass extends JFrame
    {
        final AccessMain experiment;
    
        public AccessClass(AccessMain experiment)
        {
            this.experiment = experiment;
        }
    
        public String getSubjectNumber(){
            return experiment.getSubjectNumber();
        }
    }
    

    Also, you should try Observer pattern.