Oscar F
Oscar F

Reputation: 323

Getting data from different class without re-opening JFrame in java?

Two classes in my program are causing me trouble. The first opens up a JFrame. The second updates data on a .properties file. Within the JFrame there is a panel with JTextAreas and a button "Save Changes." When that button is pressed I call a method from the second class but to do that I have to
firstClass x = new firstClass(); So when the button is pressed, the file is updated but a new JFrame opens up. I'm pretty sure creating the instance x is what's causing this, but I don't know any other way to accomplish this without doing that.

Class 1:

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

JFrame go = new JFrame("firstClass");
JPanel panel = new JPanel();
JTextArea textArea = new JTextArea();
JButton savechanges = new JButton("Save");

public firstClass() {
    panel.add(textArea);
    panel.add(savechanges);

    savechanges.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent arg0){
            secondClass f = new secondClass();
            try {
                f.UpdateData();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });

    go.add(panel);
    go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    go.setSize(750, 750);
    go.setVisible(true);
}

Class 2:

public class secondClass {
    public static void main(String[] args) {
        //creates properties file
    }

        public void UpdateData() throws IOException{
        firstClass x = new firstClass();  // <-------------------------------
        FileInputStream in = new FileInputStream("config.properties");
        Properties props = new Properties();
        props.load(in);
        in.close();

        FileOutputStream out = new FileOutputStream("config.properties");
        props.setProperty("prop1", x.textArea.getText().toString());
        props.store(out, null);
        out.close();

    }

Upvotes: 1

Views: 1344

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347204

You're crossing purposes, who's actually in control here and who is responsible for what??

Separate the areas of responsibility, for example, your SecondClass is only (really) responsible for collecting data from the user, where as your FirstClass is actually the one who knows what that data should be used, the SecondClass shouldn't care...

Think of it like this, the SecondClass is the waiter, it takes the order and gives that information to the FirstClass, who is the chef, who knows how to fulfil the order and prepare the meal...

Instead of using separate frames (see The Use of Multiple JFrames, Good/Bad Practice? for some reasons why you shouldn't), consider using a modal JDialog of some kine.

The dialog should collect the information from the user, when it is closed, based on how it is closed, use the caller to process and handle the result...

SecondClass secondClass = new SecondClass();
int reason = secondClass.showDialog();
if (reason == SAVE_RESULTS) {
    //... Get the data from the secondClass and save it...
}

See How to Make Dialogs for more details

Updated

Okay, so what you seem to want is some kind of "configuration" manager which is capable of storing/retrieving values.

The configuration manager will know how to read and write the properties and will not care about anything else, it has a clearly defined boundary. You will then need to ask the configuration manager to read or write values as needed...

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class TestConfig {

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

    JFrame go = new JFrame("firstClass");
    JPanel panel = new JPanel();
    JTextArea textArea = new JTextArea();
    JButton savechanges = new JButton("Save");

    public TestConfig() {
        panel.add(textArea);
        panel.add(savechanges);

        savechanges.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                try {
                    ConfigurationManager.INSTANCE.put("prop1", textArea.getText());
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(panel, "Failed to write properties", "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        go.add(panel);
        go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        go.setSize(750, 750);
        go.setVisible(true);

    }

    public enum ConfigurationManager {

        INSTANCE;

        protected Properties readProperties() throws IOException {
            Properties p = new Properties();
            try (FileInputStream fis = new FileInputStream("config.properties")) {
                p.load(fis);
            }
            return p;
        }

        public String get(String name) throws IOException {
            return readProperties().getProperty(name);
        }

        public void put(String key, String vaue) throws IOException {            
            Properties p =  readProperties();
            p.put(key, vaue);
            writeProperties(p);            
        }

        protected void writeProperties(Properties p) throws IOException {
            try (FileOutputStream fos = new FileOutputStream("config.properties")) {
                p.store(fos, "Config");
            }
        }            
    }
}

This example is very heavy handed...each time you read a value, it loads the contents from disk and each time you set the value, it stores to disk.

You could cache the values in memory, reading them once when it's first loaded and writing at some time the future, but I hope you get the idea none-the-less

Upvotes: 2

Related Questions