【问题标题】:initializing more than one JFrame creates blank JFrames初始化多个 JFrame 会创建空白 JFrame
【发布时间】:2014-04-25 16:30:44
【问题描述】:

我是 Swing 新手,在替换现有 JFrame 时遇到了麻烦。我初始化第一个 JFrame 没有问题...

主要:

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

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

主菜单:

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);
}

但是一旦我进入 GameDriver 并尝试初始化一个不同的 JFRame...

游戏驱动:

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

我得到一个没有所有组件的空白 JFrame(当我使用 PlacementWindow 的 main 初始化时它被正确创建)

放置窗口:

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);
}

我承认我的方法有点不合常规,但我正在尝试在并非为 swing 设计的代码的限制范围内工作(并且必须在大多数情况下保持完整)。任何帮助将不胜感激!

编辑

我已经修改了我的代码以模仿 Vince 的代码以及以下功能:

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

不幸的是,在调用 update 时,框架不会从原始 MainMenu 框架切换。有什么想法吗?

【问题讨论】:

标签: java swing jframe initialization


【解决方案1】:

不要初始化新框架。如果要从一个面板切换到另一个面板,请将框架的布局设置为 CardLayout,并添加 JPanel。

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 { }

您使用面板,因此如果需要,您可以切换/处置/创建面板而不是整个框架。

但是,对于游戏,他们不使用面板方法。游戏使用 1 个面板,而不是。如果这对你没有意义,我用一个简单的游戏设计回答了另一个问题:JFrame, JPanel, KeyListener questions

我还建议研究游戏状态。对于游戏来说,这是另一件大事。它允许您根据游戏所处的状态(菜单、游戏、暂停等)进行渲染/更新。

【讨论】:

  • 完美,感谢文斯的帮助!尽管这是一个“游戏”,但它以非常线性的方式运行,因此渲染和更新很少。也很有帮助的垃圾神,感谢您的链接!
  • 只是一些建议,以适当的速度(大约每秒 30-60 次)更新/渲染将为您提供流畅的动画。它真的让你的游戏栩栩如生。我理解您可能会担心 CPU 使用率,甚至是复杂性,但是当您感觉舒适时,我强烈建议您考虑不断更新/渲染。 (比如战舰,当一个棋子在决定他的动作时,没有人在移动他们的棋子,你仍然可以在棋盘上移动水,让你的游戏更逼真。
  • @VinceEmigh 谢谢,我知道最佳实践。这只是一个小程序,用于演示我的软件工程课程的一些开发过程。我修改了我的代码以模仿你的代码,并添加了上面的函数,但它仍然没有显示第二帧。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
相关资源
最近更新 更多