0

I'm new to Swing and I'm having trouble replacing an existing JFrame. I initialize the first JFrame without a problem...

Main:

public static JFrame jf;
public static int state = 0;

public static void main(String args[]) {
    jf = new MainMenu();
    jf.setVisible(true);
    while (state != -1) {}  
}

MainMenu:

public MainMenu() {
    setTitle("Battleship");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);

    JButton btnSinglePlayer = new JButton("Single Player - Easy");
    btnSinglePlayer.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent arg0) {
            GameDriver gd = new GameDriver(1);
        }
    });

    JButton btnSplitScreenMultiplayer = new JButton("Split Screen Multiplayer");
    btnSplitScreenMultiplayer.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent arg0) {
            GameDriver gd = new GameDriver(0);
        }
    });

    JButton btnOnlineMultiplayer = new JButton("Online Multiplayer");
    btnOnlineMultiplayer.setEnabled(false);

    JButton btnHowToPlay = new JButton("How to Play");
    btnHowToPlay.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (Desktop.isDesktopSupported()) {
                try {
                     //Set your page url in this string. For eg, I m using URL for Google Search engine
                     String url = "http://www.hasbro.com/common/instruct/battleship.pdf";
                     java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
                   }
                   catch (java.io.IOException e2) {
                       System.out.println(e2.getMessage());
                   }
            }
        }
    });
    GroupLayout gl_contentPane = new GroupLayout(contentPane);
    gl_contentPane.setHorizontalGroup(
        gl_contentPane.createParallelGroup(Alignment.LEADING)
            .addGroup(Alignment.TRAILING, gl_contentPane.createSequentialGroup()
                .addContainerGap(128, Short.MAX_VALUE)
                .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING, false)
                    .addComponent(btnHowToPlay, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnOnlineMultiplayer, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnSinglePlayer, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btnSplitScreenMultiplayer, Alignment.LEADING))
                .addGap(121))
    );
    gl_contentPane.setVerticalGroup(
        gl_contentPane.createParallelGroup(Alignment.LEADING)
            .addGroup(Alignment.TRAILING, gl_contentPane.createSequentialGroup()
                .addContainerGap(89, Short.MAX_VALUE)
                .addComponent(btnSinglePlayer)
                .addPreferredGap(ComponentPlacement.RELATED)
                .addComponent(btnSplitScreenMultiplayer)
                .addPreferredGap(ComponentPlacement.RELATED)
                .addComponent(btnOnlineMultiplayer)
                .addPreferredGap(ComponentPlacement.RELATED)
                .addComponent(btnHowToPlay)
                .addGap(45))
    );
    contentPane.setLayout(gl_contentPane);
}

But once I enter GameDriver and try to initialize a different JFRame...

GameDriver:

//Stuff Happens
ProgramShell.jf.setVisible(false);
ProgramShell.jf = new PlacementWindow(currentPlayer, otherPlayer, curShip);
ProgramShell.jf.setVisible(true);

I get a blank JFrame without all of it's components (It is created properly when I use PlacementWindow's main to initialize)

PlacementWindow:

private JPanel contentPane;
private GameBoard gbCur;
private GameBoard gbOth;
private int curPlacement;
private String title;
private int sqSize = 21;
private int xOffset = 27;
private int yOffset = 27;
private int divOffset = 283;

public PlacementWindow(GameBoard cur, GameBoard oth, int curShip) {
    this.gbCur = cur;
    this.gbOth = oth;
    this.curPlacement = curShip;
    title = "Battleship! " + cur.getName() + ", place your ships";

    setTitle(title);
    setBounds(100, 100, 518, 389);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);

    //Stuff added to Content Pane

    ImagePanel leftBoard = new ImagePanel("graphicsAssets/boardGraphic.png");
    leftBoard.setBounds(6, 6, 250, 250);
    getContentPane().add(leftBoard);

            //More stuff added to Content Pane

    contentPane.setLayout(null);
}

I recognize my approach is a little unconventional, but I'm trying to work within the limitations of code not designed for swing (and must remain, for the most part, intact). Any help would be greatly appreciated!

EDIT

I've modified my code to mimic Vince's along with the following function:

public static void update(/*New Values*/) {
   frame.remove(pp);
   secondPanel = new SecondPanel(/*New Values*/);
   frame.add(pp, "secondPanel");
   switchPanel("secondPanel");

Unfortunately The frame doesn't switch from the original MainMenu Frame upon calling update. Any Ideas?

  • Your unconventional approach isn't going to work. Create a [proper Swing view](http://java-articles.info/articles/?p=460) for your game, then move your existing code into a model. In other words, the [model - view - controller pattern](http://en.wikipedia.org/wiki/Model_view_controller). – Gilbert Le Blanc Apr 25 '14 at 16:43

1 Answers1

1

Don't initialize new Frames. If you want to switch from one panel to another, set your frame's layout to CardLayout, and add JPanels.

class MyFrame {

    static CardLayout cl = new CardLayout(); //handles panel switching

    static JFrame frame; //init swing on EDT
    static FirstPanel firstPanel;
    static SecondPanel secondPanel;

    public static void main(String[] args) {
         initFrame();
    }

    public static void initFrame() {
         SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                   frame = new JFrame();
                   frame.setDefaultCloseOperation(3);
                   frame.setLayout(cl);

                   firstPanel = new FirstPanel();
                   secondPanel = new SecondPanel();


                   //first panel added to frame will always show first
                   frame.add(firstPanel, "first");
                   frame.add(secondPanel, "second");
                   frame.pack(); //sizes frame to fit the panel being shown

                   setVisible(true);
              }
         });
    }

    public static void switchPanel(String name) {
         cl.show(frame.getContentPane(), name);
         frame.pack();
    }
}   

class FirstPanel extends JPanel { }
class SecondPanel extends JPanel { }

You use panels so if needed, you can switch/dispose/create panels instead of the entire frame.

BUT, as for games, they don't use the panel approach. Games use 1 panel, and instead. If this doesn't make sense to you, I answered another question with a simple game design: JFrame, JPanel, KeyListener questions

I also suggest looking into Game States. This is another big deal when it comes to games. It allows you to render/update depending on what state the game is at (menu, game, pause, ect..)

Community
  • 1
  • 1
Vince
  • 14,470
  • 7
  • 39
  • 84
  • Perfect, Thanks for the help Vince! Despite this being a 'game', it runs in a very linear fashion so rendering and updating is minimal. Also helpful trashgod, thanks for the link! – Agent J Wall Apr 25 '14 at 17:45
  • Just some advice, updating/rendering at a decent speed (about 30-60 times per second) will give you fluent animations. It really brings your game to life. I understand how you might be worried about CPU usage, or even complexity, but when you feel comfortable, I HIGHLY suggest looking into constant updating/rendering. (such as for battleship, when a play is deciding his move, and no one is moving their pieces, you could still have moving water on the game board, making your game a bit more life-like. – Vince Apr 25 '14 at 17:54
  • @VinceEmigh Thanks, I'm aware of best practices. This was just a small program to demonstrate some development processes for my Software Engineering course. I've modified my code to mimic yours plus added the function above, but it still isn't showing the second frame. Any Ideas? – Agent J Wall Apr 25 '14 at 21:39