Search code examples
javaswingjframejlabel

Java - Broken JLabel after proper disposal of different JFrame


I'm currently making our project and I'm having problem reseting JLabel back to "0". Here's the code

main code snippet (check note 1 for frame disposal method used):

import javax.swing.*;                                                       //import library
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class draft_main                                                     //class name
{
    public static void main(String[] args)            
    {                                                                       //method name
        JFrame f0 = new JFrame("POS");                                      //frame
        JPanel p0 = new JPanel();                                           //panel inside the frame
        JPanel p1 = new JPanel();
        JPanel p2 = new JPanel();
        JPanel p3 = new JPanel();
        JPanel p4 = new JPanel();
        JPanel p5 = new JPanel();
        JPanel p6 = new JPanel();
        JPanel p7 = new JPanel();
        JLabel l0 = new JLabel("Amount:");                                  //label inside the panel
        JLabel l1 = new JLabel("0");
        JLabel l2 = new JLabel("Menu Code: ");
        JLabel l3 = new JLabel("--Menu--");
        JTextField tf0 = new JTextField("", 12);                            //user input for menu code
        JButton b0 = new JButton("Checkout");                               //buttons
        JButton b1 = new JButton("Cancel");
        JButton b2 = new JButton("Exit");
        JButton b4 = new JButton("Accept");
        JButton b7 = new JButton("Remove");
        JOptionPane jop = new JOptionPane();                                //JOptionPane
        JTextField tf1 = new JTextField("1. Hot Pockets Pizza", 20);        //list of menu
        JTextField tf2 = new JTextField("2. Burger with Fries", 20);
        JTextField tf3 = new JTextField("3. Sticky Rice (Bico)", 20);
        ArrayList<String> ar = new ArrayList<String>();                     //list of array

        try{
            b4.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)              //what the accept button does
                    {
                        String order = tf0.getText(), tots="", temp="";
                        int o = Integer.parseInt(order);
                        int tot=0;

                        switch(o)                                           //menu choice
                        {
                            case 1 : temp = l1.getText(); tot=Integer.parseInt(temp); tot=tot+250; tots = Integer.toString(tot); l1.setText(tots); ar.add("Hot Pockets Pizza"); break;
                            case 2 : temp = l1.getText(); tot=Integer.parseInt(temp); tot=tot+65; tots = Integer.toString(tot); l1.setText(tots); ar.add("Burger with Fries"); break;
                            case 3 : temp = l1.getText(); tot=Integer.parseInt(temp); tot=tot+12; tots = Integer.toString(tot); l1.setText(tots); ar.add("Sticky Rice (Bico)"); break;
                            default : jop.showMessageDialog(null, "Menu code not listed in menu", "Error", jop.INFORMATION_MESSAGE); break;
                        }
                    }
                });

            b0.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)              //what the checkout button does
                    {
                        JFrame f1 = new JFrame("Checkout");
                        JFrame f2 = new JFrame("Order");
                        JPanel p8 = new JPanel();
                        JPanel p9 = new JPanel();
                        JPanel p10 = new JPanel();
                        JPanel p11 = new JPanel();
                        JPanel p12 = new JPanel();
                        JPanel p13 = new JPanel();
                        JPanel p14 = new JPanel();
                        JLabel l5 = new JLabel("Order list");
                        JLabel l6 = new JLabel(/*convert ArrayList to String then put here*/);
                        JLabel l4 = new JLabel("Cash");
                        JTextField tf4 = new JTextField("", 14);
                        JButton b5 = new JButton("Accept");
                        JButton b6 = new JButton("Cancel");
                        JButton b7 = new JButton("Ok");

                        b5.addActionListener(new ActionListener()
                            {
                                public void actionPerformed(ActionEvent e)
                                {
                                    String cas = l1.getText(), in = tf4.getText();
                                    int cash = Integer.parseInt(cas), inp = Integer.parseInt(in), cahs=0;

                                    if(cash>inp)
                                    {
                                        jop.showMessageDialog(null, "Insufficient funds", "Lacking cash? Work for it.", jop.INFORMATION_MESSAGE);
                                    }
                                    else if(cash<inp)
                                    {
                                        cahs = inp - cash;
                                        jop.showMessageDialog(null, "Change: " +cahs+". Thank you");
                                        f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
                                    }
                                    else if(cash==inp)
                                    {
                                        jop.showMessageDialog(null, "Thank you.", "Thank you.", jop.INFORMATION_MESSAGE);
                                        f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
                                    }
                                }
                            });

                        b6.addActionListener(new ActionListener()
                            {
                                public void actionPerformed(ActionEvent e)
                                {
                                    f1.dispatchEvent(new WindowEvent(f1, WindowEvent.WINDOW_CLOSING));
                                }
                            });

                        b7.addActionListener(new ActionListener()
                            {
                                public void actionPerformed(ActionEvent e)
                                {
                                    f2.dispatchEvent(new WindowEvent(f2, WindowEvent.WINDOW_CLOSING));
                                }
                            });

                        p9.add(l0);
                        p9.add(l1);
                        p10.add(l4);
                        p10.add(tf4);
                        p11.add(b5);
                        p11.add(b6);
                        p12.add(l5);
                        p12.add(l6);
                        p13.add(b7);
                        p14.add(p12);
                        p14.add(p13);
                        p8.add(p10);
                        p8.add(p11);
                        p8.add(p9);
                        f1.add(p8);
                        f1.pack();
                        f1.setSize(240,170);
                        f1.setLocationRelativeTo(null);
                        f1.setResizable(false);
                        f1.setDefaultCloseOperation(f1.DISPOSE_ON_CLOSE);
                        f1.setVisible(true);
                        f2.add(p14);
                        f2.pack();
                        f2.setSize(270,100);
                        f2.setResizable(false);
                        f2.setLocationRelativeTo(null);
                        f2.setDefaultCloseOperation(f2.DISPOSE_ON_CLOSE);
                        f2.setVisible(true);
                    }
                });

            b1.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        l1.setText("0");
                    }
                });

            b2.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    f0.dispose();
                }
            });
        }

        catch(Exception e)
        {
            jop.showMessageDialog(null, "Error");
        }

        tf1.setEditable(false);
        tf2.setEditable(false);
        tf3.setEditable(false);
        p4.add(tf1);
        p5.add(tf2);
        p6.add(tf3);
        p7.add(l3);
        p3.add(l2);
        p3.add(tf0);
        p3.add(b4);
        p1.add(l0);
        p1.add(l1);
        p2.add(b0);
        p2.add(b1);
        p2.add(b2);
        p0.add(p3);
        p0.add(p1);
        p0.add(p2);
        p0.add(p7);
        p0.add(p4);
        p0.add(p5);
        p0.add(p6);
        f0.add(p0);
        f0.pack();
        f0.setSize(303,280);
        f0.setLocationRelativeTo(null);
        f0.setResizable(false);
        f0.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f0.setVisible(true);
    }
}

what happens is when the main window opens it asks for which from the menu did a guy order then it displays the price. During checkout the user will be asked to input amount of cash given and gives change if there's any. After then the checkout frame is then "properly" disposed (so as I think so), exposing the main frame. However the JLabel does not seem to update when I place another order or clear the current order and it bothers me since the main frame is supposed to be fully interactive until the main frame is closed.

note #1: I have used different methods on how to dispose the 2nd and 3rd frame which pops up since I thought it may have been because of the dispose(); does not really destroys the frame but let's it run in the background.

note #2: yes the program is not finished yet, but those don't matter for now for those will just be some minor features of the application.


Solution

  • You've several problems with this code, but the major ones that I see (and I haven't gone through all of it yet, so there may be more)

    • First and foremost, those JFrame sub-windows shouldn't be JFrames at all, but rather should be modal JDialogs. The reason for this is this gives you complete control over program flow when these dialogs are used, since you'll then know that the main program flow will be put on hold while the modal dialog is visible, and then the flow will resume as soon as the dialog is no longer visible. This way you can query the state of the dialog after it has been dealt with, and then use this information to update your GUI.
    • Your amount is shown in the l1 variable, and this will never change unless you specifically call setText(...) on this variable. You don't seem to be doing it when the order has been processed. Again modal dialogs will help you with this.
    • Your variable naming is bad. Instead of using meaningless letters and numbers for names, use names that make sense and that make your code self-commenting. So for instance, instead of l1, use amountLabel or something similar.
    • Your code is one huge god class with everything stuffed into the static main method, and this makes for a debugging nightmare. Java is an object-oriented language, and if used properly OOP techniques can help you reduce program complexity making your code easier for yourself and for us to understand. Start OOP-ifying your program and you'll see immediate dividends.

    • And I found your bug -- you're adding the l1 JLabel to another container, and so it is effectively being removed from the original JFrame. If you minimize your original GUI and then restore it, you'll see the amount l1 JLabel disappear.

    Here's some sample code not yet done, but to give you an idea about adding OOP to the program:

    import java.awt.Font;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.text.NumberFormat;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class Draft2 extends JPanel {
        private List<MyItem> selectedItems = new ArrayList<>();
        private NumberFormat formatter = NumberFormat.getCurrencyInstance();
        private double total;
        private JLabel totalAmountLabel = new JLabel(formatter.format(total));
        private DefaultComboBoxModel<MyItem> comboModel = new DefaultComboBoxModel<>();
        private JComboBox<MyItem> menuCombo = new JComboBox<>(comboModel);
    
        public Draft2() {
            // monospaced to make names and price line up
            menuCombo.setFont(new Font(Font.MONOSPACED, Font.BOLD, 12));
    
            // fill the JComboBox with items
            comboModel.addElement(new MyItem("Baseball", 21.5));
            comboModel.addElement(new MyItem("Bat", 50.8));
            comboModel.addElement(new MyItem("Football", 22.26));
    
            // create a JPanel to hold selection components and add components
            JPanel selectionPanel = new JPanel();
            selectionPanel.add(new JLabel("Menu:"));
            selectionPanel.add(menuCombo);
            selectionPanel.add(new JButton(new AcceptAction("Accept", KeyEvent.VK_A)));
    
            // create a JPanel to hold the total amount information
            JPanel totalAmountPanel = new JPanel();
            totalAmountPanel.add(new JLabel("Total Amount:"));
            totalAmountPanel.add(totalAmountLabel);
    
            // create a JPanel to hold buttons, uses grid layout with a single row  
            JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0)); 
            btnPanel.add(new JButton(new CheckOutAction("Check Out", KeyEvent.VK_C)));
            btnPanel.add(new JButton(new CancelAction("Cancel", KeyEvent.VK_N)));
            btnPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
    
            setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
            add(selectionPanel);
            add(Box.createVerticalStrut(5)); // so don't crowd things
            add(totalAmountPanel);
            add(Box.createVerticalStrut(5));
            add(btnPanel);
        }
    
        public void setTotalAmount(double total) {
            totalAmountLabel.setText(formatter.format(total));
        }
    
        private class AcceptAction extends AbstractAction {
    
            public AcceptAction(String name, int mnemonic) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                MyItem myMenuItem = (MyItem) menuCombo.getSelectedItem();
                if (myMenuItem == null) {
                    return; // nothing selected, get out
                }
                selectedItems.add(myMenuItem);
                double total = 0.0;
                for (MyItem myItem : selectedItems) {
                    total += myItem.getCost();
                }
    
                setTotalAmount(total);
            }
        }
    
        private class CheckOutAction extends AbstractAction {
            public CheckOutAction(String name, int mnemonic) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Finish....
                // open JDialog or JOptionPane
    
            }
        }
    
        private class CancelAction extends AbstractAction {
            public CancelAction(String name, int mnemonic) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Finish...
    
            }
        }
    
        private class ExitAction extends AbstractAction {
            public ExitAction(String name, int mnemonic) {
                super(name);
                putValue(MNEMONIC_KEY, mnemonic);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
    
            }
        }
    
        private static void createAndShowGui() {
            JFrame frame = new JFrame("My GUI Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new Draft2());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
                    createAndShowGui();            
            });
        }
    }
    
    class MyItem {
        private NumberFormat formatter = NumberFormat.getCurrencyInstance();
        private String name;
        private double cost;
        public MyItem(String name, double cost) {
            this.name = name;
            this.cost = cost;
        }
    
        public String getName() {
            return name;
        }
    
        public double getCost() {
            return cost;
        }
    
        @Override
        public String toString() {
            return String.format("%-10s %s", name, formatter.format(cost));
        }
    }