2

So I want to have everything removed from my JFrame when a string equals a certain value, but when I call removeAll(); followed by revalidate(); and repaint();, it doesn't change anything.

I have tried calling getContentPane.removeAll(); as directed here, but that did not do anything.

My code is as follows:

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

public class MTGSAMPServerReference extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    private static JList list1;
    private static JButton select1;
    public static String selectionMenu = "Main";

    public MTGSAMPServerReference() {
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
            Object[]mainMenu = {"Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP", "FAQ's"};
                Object[]VehiclesValueMenu = {"Lower Class", "Upper Class", "VIP"};
        if ("Main".equals(selectionMenu)) {
            JPanel controls = new JPanel(new BorderLayout(5,5));
            list1 = new JList<Object>(mainMenu);
            list1.setVisibleRowCount(10);
            select1 = new JButton("Select");
            select1.addActionListener(this);
            controls.add(new JScrollPane(list1));
            controls.add(select1, BorderLayout.PAGE_END);
            controls.setBorder(new EmptyBorder(25,25,0,0));
            add(controls);
            revalidate();
            repaint();
        }
        if ("VehiclesValue".equals(selectionMenu)) {
            removeAll();
            revalidate();
            repaint();
        }

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if ("Main".equals(selectionMenu)) {
            if (e.getActionCommand().equals("Select")) {
                int indexMain = list1.getSelectedIndex();
                System.out.println("Index Selected: " + indexMain);
                String valueMain = (String) list1.getSelectedValue();
                System.out.println("Value Selected: " + valueMain);
                if ("Vehicles".equals(valueMain)) {
                    selectionMenu = "VehiclesValue";
                    System.out.println("Menu selected: " + selectionMenu);
                    revalidate();
                    repaint();
                }
            }
        }
    }

    public void createAndShowGUI() {
        JFrame f = new MTGSAMPServerReference();
        f.pack();
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //f.add(new drawOnPanel());
        f.setSize(1200, 800);
        f.setLocationRelativeTo(null);
        list1.setSize(250, 250);
        list1.setLocation(0, 0);
        select1.setSize(75, 25);
        select1.setLocation(251, 276);
        MTGSAMPServerReference.this.repaint();
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
            MTGSAMPServerReference gui = new MTGSAMPServerReference();
            gui.createAndShowGUI();
            }
        });
    }
}

I have done my research, but can't figure out what it is that I am doing wrong.

And if I try changing my JFrame f to a Global Variable instead of a Local Variable, it doesn't display anything to begin with.

And yes, I know I am mixing Commmand Line with GUI, but that is only for debugging purposes. When I am finished, I will simply remove everything Command Line related.

Anyways, any ideas on my problem?

And thanks in advance!

Community
  • 1
  • 1
knorberg
  • 462
  • 5
  • 19
  • 2
    `static` variables is a pretty good indication of a bad design – MadProgrammer Jul 26 '13 at 11:28
  • 2
    For this, I'd use a [`CardLayout`](http://docs.oracle.com/javase/7/docs/api/java/awt/CardLayout.html) as seen in this [short example](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Jul 26 '13 at 11:29
  • I think your design is pretty mucked up. You seem to be assuming if you construct two different instance of a class, you can some how magically effect the other. This isn't going to work, hence my first comment... – MadProgrammer Jul 26 '13 at 11:30
  • @MadProgrammer Then how would you suggest I access them? If they aren't static, then I can't access them as I would be trying to access a non-static variable from a static context? (Sorry, I suck with static) – knorberg Jul 26 '13 at 11:31
  • 1
    Via an instance of the container – MadProgrammer Jul 26 '13 at 11:32
  • @MadProgrammer And once you criticize my code, would you mind offering a solution? I am wide open to criticism, although it is more helpful if a suggestion is also given. Thanks – knorberg Jul 26 '13 at 11:32
  • 2
    `list1` and `select1` don't need to be `static`, as they should belong to a single instance of `MTGSAMPServerReference`. `selectionMenu` doesn't have to be `static` as it could be passed as parameter to the `MTGSAMPServerReference` constructor. If you need access to the values contained by the `JList` or `JButton`, you should supply getters and setters as required. You should avoid exposing sub components to the outside world if you can avoid it, as this means others suddenly gain control over you entire component and can do things you have no means to stop – MadProgrammer Jul 26 '13 at 11:38
  • @MadProgrammer Thanks for the suggestion! I will try to use that from now on! +1 For the information and the huge help! – knorberg Jul 26 '13 at 11:44
  • 1
    *"once you criticize my code, would you mind offering a solution?"* I don't think this is a very helpful comment. 1) The person who offers the advice might not know the answer, but still be able to recognize code that will cause problems (I agree about the use of `static` - which is rarely, if ever, a solution). 2) Fixing the thing they point out might actually *be* the solution, or 90% of the way to one, and.. 3) It comes off as sounding like 'unless you intend to supply an answer, don't criticize my code'. Usually people have your best interests at heart, when they 'rip code to pieces'. – Andrew Thompson Jul 26 '13 at 11:45
  • @AndrewThompson Ok, so I have implemented the `Card Layout` in my code and tried running it, but I do not see where it removes all the components. Any ideas? – knorberg Jul 26 '13 at 11:46
  • @AndrewThompson I wasn't implying "if you don't have a solution, then don't criticize my code". Sorry for the confusion. I was simply asking that if he did have a solution, would he mind sharing it. In the past, people would say how crappy my code would look, but just leave it at that. I would have to ask them specifically about each and every detail about my code that "looked crappy" for them to offer up suggestions. My experience has been that sometimes people forget that criticism isn't always the "whole pie" but usually just a "tasty slice of it". (If that makes sense) – knorberg Jul 26 '13 at 11:51
  • @MadProgrammer Ok, so I have researched `getters`, and from what I understand, a `getter` is simply setting a method to a String (in this case) and returning the String to the method with `return String;`. Is this correct? – knorberg Jul 26 '13 at 11:56
  • 1
    It can return anything you want to it return. For example, you could write a getter or setter that gets/sets the selected item. For example, `JList` has `set/getVisibleRowCount` which interacts with an internal instance variable. – MadProgrammer Jul 26 '13 at 12:02
  • @MadProgrammer That is `supplying a getter` though, correct? – knorberg Jul 26 '13 at 12:03
  • I'm not sure I understand the question – MadProgrammer Jul 26 '13 at 12:17
  • @MadProgrammer I mean, using `return variable;` is suppling a getter correct? – knorberg Jul 26 '13 at 13:01
  • Ok, both the answers given (@MadProgrammer & @DSquare) work. But I am going to choose the one given by DSquare as the correct answer because it just clears the JFrame and keeps all of my components as I had them. Thanks to both of you though! I will be combining the two answers! – knorberg Jul 26 '13 at 13:10

2 Answers2

2

This is an example using a CardLayout which does away with the static variables and provide access to some of the inner values via setters and getters, for demonstration

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;

public class MTGSAMPServerReference extends JFrame implements ActionListener {

    private JList list1;
    private JButton select1;
    private String selectionMenu;
    private JPanel mainMenuPane;
    private JPanel vehicleMenuPane;

    public MTGSAMPServerReference(String selectionMenu) {
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
        Object[] mainMenu = {"Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP", "FAQ's"};
        Object[] VehiclesValueMenu = {"Lower Class", "Upper Class", "VIP"};

        mainMenuPane = new JPanel(new BorderLayout(5, 5));
        list1 = new JList<Object>(mainMenu);
        list1.setVisibleRowCount(10);
        select1 = new JButton("Select");
        select1.addActionListener(this);
        mainMenuPane.add(new JScrollPane(list1));
        mainMenuPane.add(select1, BorderLayout.PAGE_END);
        mainMenuPane.setBorder(new EmptyBorder(25, 25, 0, 0));

        vehicleMenuPane = new JPanel();
        vehicleMenuPane.add(new JLabel("Vehicle"));

        CardLayout cl = new CardLayout();
        setLayout(cl);
        add("main", mainMenuPane);
        add("vehicle", vehicleMenuPane);

        cl.show(getContentPane(), "main");

        setSelectionMenu(selectionMenu);

    }

    public String getSelectionMenu() {
        return selectionMenu;
    }

    public void setSelectionMenu(String value) {
        if (selectionMenu == null ? value != null : !selectionMenu.equals(value)) {
            selectionMenu = value;
            updateMenu();
        }
    }

    protected void updateMenu() {
        CardLayout cl = (CardLayout) getContentPane().getLayout();
        if ("Main".equals(selectionMenu)) {
            cl.show(getContentPane(), "main");
        } else if ("VehiclesValue".equals(selectionMenu)) {
            cl.show(getContentPane(), "vehicle");
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if ("Main".equals(selectionMenu)) {
            if (e.getActionCommand().equals("Select")) {
                int indexMain = list1.getSelectedIndex();
                System.out.println("Index Selected: " + indexMain);
                String valueMain = (String) list1.getSelectedValue();
                System.out.println("Value Selected: " + valueMain);
                if ("Vehicles".equals(valueMain)) {
                    setSelectionMenu("VehiclesValue");
                    System.out.println("Menu selected: " + selectionMenu);
                }
            }
        } else {
            setSelectionMenu("Main");
        }
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                MTGSAMPServerReference gui = new MTGSAMPServerReference("Main");
                gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                gui.pack();
                gui.setLocationRelativeTo(null);
                gui.setVisible(true);
            }
        });
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

I see several problems with that code:

  • MTGSAMPServerReference is called two times, one in the main, and another by createAndShowGUI().

  • MTGSAMPServerReference extends JFrame, but createAndShowGUI() contains a local variable JFrame f too. Esentially you are assigning this to a local variable f, which serves no purpose.

  • To initialize the GUI you execute the constructor and createAndShowGUI(), after that all the code that can be executed is due to events. In your case in the actionPerformed() method. If you want to remove the components inside the frame, you have to do the proper code there (or at some point called from there).

  • As stated by your link, to remove all components you have to execute removeAll() on the contentPane of the JFrame, obtained with getContentPane().

  • I don't know what you intend to do with those comparations if("Main".equals(selectionMenu)). Again that is initialization code, it's ran once. There you build all the GUI. The variable selectionMenu may change in the future, but that doesn't retroactively execute that code. If you want to do anything using the new value of selectionMenu, do it on the actionListener.

Here's a working modification of your code.

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

public class MTGSAMPServerReference extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    private static JList list1;
    private static JButton select1;
    public static String selectionMenu = "Main"; //accomplishes nothing

    public static void main(String[] args) 
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
            MTGSAMPServerReference gui = new MTGSAMPServerReference();
            gui.createAndShowGUI();
            }
        });
    }

    public void createAndShowGUI() {
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //f.add(new drawOnPanel());
        setSize(1200, 800);
        setLocationRelativeTo(null);
        list1.setSize(250, 250);
        list1.setLocation(0, 0);
        select1.setSize(75, 25);
        select1.setLocation(251, 276);
        setVisible(true);
    }


    public MTGSAMPServerReference() {
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
            Object[]mainMenu = {"Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP", "FAQ's"};
                Object[]VehiclesValueMenu = {"Lower Class", "Upper Class", "VIP"};
            JPanel controls = new JPanel(new BorderLayout(5,5));
            list1 = new JList<Object>(mainMenu);
            list1.setVisibleRowCount(10);
            select1 = new JButton("Select");
            select1.addActionListener(this);
            controls.add(new JScrollPane(list1));
            controls.add(select1, BorderLayout.PAGE_END);
            controls.setBorder(new EmptyBorder(25,25,0,0));
            add(controls);
            //revalidate(); //uneeded at this point the JFrame is not yet visible, thus nothing to repaint
            //repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Select")) {
            int indexMain = list1.getSelectedIndex();
            System.out.println("Index Selected: " + indexMain);
            String valueMain = (String) list1.getSelectedValue();
            System.out.println("Value Selected: " + valueMain);
            if ("Vehicles".equals(valueMain)) {
                System.out.println("Menu selected: " + selectionMenu);
                getContentPane().removeAll(); //equivalent to this.getContentPane().removeAll();
                revalidate();
                repaint();
            }
        }
    }  
} 

Also I've erased the modifications of the variable selectionMenu it doesn't really do anything now.

As stated by others, you probably want to use another Layout at some point. Which one depends on what else you want on the JFrame.

Cheers.

DSquare
  • 2,458
  • 17
  • 19