MineAndCraft12
MineAndCraft12

Reputation: 671

Multiple JFrames in One Application

I am still learning Java's Swing package, and I'm making an application that tracks how many frappucinos one has purchased / eaten. I have come to a huge error.

There's a button in the application that, when clicked, will open another JFrame that acts like JavaScript's prompt() command. I know that this works on its own, before adding the main JFrame this worked perfectly when called in the code.

But when I try to click the button to make the second JFrame, the entire app freezes and proceeds to use up 50% of my RAM. When this occurs, I cannot close the program and have to end it with Task Manager.

Here is my code...

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.nio.file.*;

class Frappucinos{
    //initialize the main window
    public static JFrame window;

    // initializing values for ask()
    private static String inValue;
    private static boolean askPush = false;
    // popup asking box, like JavaScript's prompt()
    private static String ask(String message){
        // setup frame
        JFrame askPane = new JFrame("Frappucinos");
        askPane.setLayout(null);
        askPane.setBounds(150, 100, 300, 200);
        // setup question label
        JLabel askText = new JLabel(
            message,
            SwingConstants.CENTER
        );
        askText.setBounds(0, 25, 300, 25);
        // setup input field
        JTextField askType = new JTextField(25);
        askType.setBounds(50, 75, 200, 25);
        // setup button
        JButton askButn = new JButton("Submit");
        askButn.setBounds(100, 125, 100, 25);
        // add elements to frame
        askPane.add(askText);
        askPane.add(askType);
        askPane.add(askButn);
        // make buttons click event
        askButn.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent evt){
                // set variable to content of the textfield
                inValue = askType.getText();
                // tell program button has been pushed
                askPush = true;
                //hide window
                askPane.setVisible(false);
            }
        });
        // set size of window and make it visible
        askPane.setMinimumSize(new Dimension(300, 200));
        askPane.setPreferredSize(new Dimension(300, 200));
        askPane.setMaximumSize(new Dimension(300, 200));
        askPane.setLocationRelativeTo(null);
        askPane.setVisible(true);
        // tell program button hasn't been pushed yet
        askPush = false;
        // suspend program until button is pushed
        // i know, this is not a very good way of doing it...
        while(!askPush){}
        // return the value
        return inValue;
    }

    // initializing frapp eating variables
    public static String obtaining;
    public static String eating;
    public static Integer obtained;
    public static Float eaten;
    public static String buyAmount;
    public static String eatAmount;
    public static Integer eatInt;

    // writing to files
    public static void fileWrite(String fPath, String fContent){
        FileOutputStream fileOut;
        try{
            fileOut = new FileOutputStream(fPath);
            new PrintStream(fileOut).println(fContent);
            fileOut.close();
        }catch(IOException e){
            System.out.println(" Unable to write to file " + fPath);
            System.exit(0);
        }
    }

    public static void main(String[] args){
        // set file path
        Path file = Paths.get("bought.txt");
        try{
            // create the file
            Files.createFile(file);
        // if it already exists
        }catch(FileAlreadyExistsException x){
            System.out.println(" File bought.txt already exists");
        }catch(IOException x){
        // if theres an error
            System.out.println(" Error making file bought.txt:");
            System.out.println(x);
        }
        // make an input stream
        FileInputStream fileIn;
        try{
            // the input file stream ready
            fileIn = new FileInputStream("bought.txt");
            // read a line
            obtaining = new DataInputStream(fileIn).readLine();
            // if line is blank
            if(obtaining == null){
                // make variable 0
                obtaining = "0";
            }
            // close the file
            fileIn.close();
        // errors
        }catch(IOException e){
            System.out.println(" Unable to read from file bought.txt");
            // make variable 0
            obtaining = "0";
        }
        // set file path
        file = Paths.get("eaten.txt");
        try{
            // make the file
            Files.createFile(file);
        // if already there
        }catch(FileAlreadyExistsException x){
            System.out.println(" File eaten.txt already exists.");
        // if errors
        }catch(IOException x){
            System.out.println(" Error making file eaten.txt:");
            System.out.println(x);
        }
        try{
            // set file input stream to new file
            fileIn = new FileInputStream("eaten.txt");
            // set variable to line in file
            eating = new DataInputStream(fileIn).readLine();
            // if blank then make it 0.0
            if(eating == null){
                eating = "0.0";
            }
            // close that file
            fileIn.close();
        // if theres an error
        }catch(IOException e){
            // do the same stuff as all the other ones did...
            System.out.println(" Unable to read from file eaten.txt");
            eating = "0";
        }
        obtained = Integer.valueOf(obtaining);
        eaten = Float.parseFloat(eating);

        window = new JFrame("Frappucinos");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton buyFrapp = new JButton("Bought a Frapp");
        JButton eatFrapp = new JButton("Drank some Frapp");
        JLabel frappDet = new JLabel("Loading...", SwingConstants.CENTER);
        window.setLayout(null);
        window.setBounds(    0,  0, 600, 500);
        buyFrapp.setBounds( 25, 25, 100,  25);
        eatFrapp.setBounds(475, 25, 100,  25);
        frappDet.setBounds(  0, 75, 600, 425);
        buyFrapp.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent evt){
                buyAmount = ask("How many frappucinos have you bought?");
                obtained = obtained + Integer.parseInt(buyAmount);
                fileWrite("bought.txt", "" + obtained);
            }
        });
        eatFrapp.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent evt){
                eatAmount = ask("What percentage of a frappucino have you eaten (without % sign)");
                eatInt = Integer.parseInt(eatAmount);
                if(eatInt > 99){
                    eaten = eaten + Float.parseFloat("" + eatInt / 100 + "." + (eatInt - ((eatInt / 100) * 100)));
                }else if(eatInt > 9){
                    eaten = eaten + Float.parseFloat("0.0" + eatAmount);
                }else{
                    eaten = eaten + Float.parseFloat("0." + eatAmount);
                }
                fileWrite("eaten.txt", "" + eaten);
            }
        });
        window.add(buyFrapp);
        window.add(eatFrapp);
        window.add(frappDet);
        window.setLocationRelativeTo(null);
        window.setVisible(true);
    }
}

I added the entire code because I know that adding small bits of it can sometimes not include important features of it.

To clarify, what I need to happen is for the new JFrame to appear when the buttons are clicked. But what really happens is the app freezes and begins to use 50% of my RAM.

If any extra details or clarifications are needed, feel free to post them and I will answer as soon as I see them.

Yes, I have done research in many places, including Stack Overflow, but nothing that I have seen helps, and I don't want a JInternalFrame.

Upvotes: 1

Views: 2149

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285430

Here:

    // suspend program until button is pushed
    // i know, **this is not a very good way of doing it...** (emphasis mine)
    while(!askPush){}

as you already know, this "is not a very good way of doing it...". It's not only not a very good way, it's a terrible way and will freeze up your Swing event thread and is not how event driven programming should be done. Simply don't do this.

What you want to use instead is a modal dialog such as a JOptionPane or a modal JDialog. This will freeze your calling code at the time of the request while not freezing the Swing event thread. The calling code will resume once the dialog is no longer visible.

Other issues:

  • Your program is little more than one big bunch of static fields and methods with no true classes that have state and behavior. It's as if you're trying to shove a console program into an event-driven program. Don't do this. Instead first extract out the non-GUI objects that will be needed and make classes for them. Then create a GUI with true non-static methods and fields and that uses the non-GUI objects as its "model".
  • Examples of modal dialogs:

Upvotes: 6

Related Questions