有时只从actionPerformed函数调用的pack方法

时间:2016-11-26 06:41:21

标签: java swing jframe jpanel

问题

多次编译并运行我的程序后,有时候pack()会正常工作,而newGamePanel的组件会被压缩,有时它不起作用,而newGamePanel会扩展为填充由JFrame设置的setSize()值。我无法可靠地重现任何结果 - 它似乎是随机的。

注意:由于我减少了GUI格式的数量以便审查合理数量的代码,因此GUI非常糟糕。但是,问题仍然很容易识别。当JPanel显示应该打包的CardLayout时,有时JFrame是"打包"大小,有时它匹配我在开头设置的setSize()值。现在我切断了GUI,newGamePanel组件不会移动来填充他们的容器,但这仅仅是因为我删除了所有约束值。

怀疑和设计

我从类pack()调用TankEvent,它实现了ActionListener。游戏是TankApplication对象(TankApplication扩展JFrame)传递给TankEvent构造函数中的TankEvent,由TankDisplay调用TankDisplay JPanel 1}}扩展JFrame)。

JPanel实例化JPanel,传递self的实例。 ActionListener实例化ActionListener,传递自我的实例。 JFrame使用pack()修改CardLayout layOut = (CardLayout)(display.getLayout()); //display is an object of TankDisplay layOut.show(display, "newGamePanel"); game.pack(); //game is an object of TankApplication game.setResizable(false); break;

以下是按下按钮时执行的代码。

pack()

我想知道问题是否在我的设计中。我做了一个很大的假设,JFrame重新绘制了JFramesJFrame甚至重新绘制了?也许是重新验证/更新?)。但只要我在完成时重置display.getLayout()的大小,我就不确定为什么会出现这个问题。

(旁边的问题,我不确定为什么我需要将CardLayout强制转换为getLayout()。这是docs.oracle建议的实现,但为什么package Tanks; import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.io.*; import java.net.URL; import javax.imageio.*; public class TankDisplay extends JPanel{ JCheckBox unlimitedAmmoCB, unlimitedTimeCB; JTextField playerOneTF, playerTwoTF; JPanel menuPanel, newGamePanel; public TankDisplay(TankApplication g){ TankEvent listener = new TankEvent(this, g); //passing an instance of self and previously received instance of TankApplication to TankEvent setLayout(new CardLayout()); //Hihghest level of GUI after JFrame. CardLayout for overall display JPanel, need for switching functionality in TankEvent menuPanel = new JPanel(new GridBagLayout()); //Second highest level of GUI. Will eventually display a picture instead of a black JPanel. Has button "New Game" and "Load Game" JPanel mainMenuImageP = new JPanel(); GridBagConstraints conMainMenuImageP = new GridBagConstraints(); mainMenuImageP.setBackground(Color.BLACK); conMainMenuImageP.fill = GridBagConstraints.BOTH; conMainMenuImageP.gridy = 0; conMainMenuImageP.gridx = 0; menuPanel.add(mainMenuImageP, conMainMenuImageP); //adding menuPanel components JButton newGameB = new JButton("New Game"); GridBagConstraints conNewGameB = new GridBagConstraints(); conNewGameB.fill = GridBagConstraints.NONE; conNewGameB.gridy = 1; conNewGameB.gridx = 0; menuPanel.add(newGameB, conNewGameB); //adding menuPanel components JButton loadGameB = new JButton("Load Game"); GridBagConstraints conLoadGameB = new GridBagConstraints(); conLoadGameB.fill = GridBagConstraints.NONE; conLoadGameB.gridy = 1; conLoadGameB.gridx = 1; menuPanel.add(loadGameB, conLoadGameB); //adding menuPanel components //action listners for mainPenu panel components newGameB.addActionListener(listener); add(menuPanel, "menuPanel"); //menuPanel is added to higher display JPanel newGamePanel = new JPanel(new GridBagLayout()); //creating second higher level container. To achieve certain functionality, //this panel contains four other panels, that each contain their own JPanel playerOneSetUp = new JPanel(new GridBagLayout()); //components. newGamePanel uses GridBagLayout, and so do the panels GridBagConstraints conPlayerOneSetUp = new GridBagConstraints();//that it's managing. GridBayLayout managaing GridBagLayout conPlayerOneSetUp.fill = GridBagConstraints.BOTH; conPlayerOneSetUp.gridy = 0; conPlayerOneSetUp.gridx = 0; JLabel playerOneL = new JLabel("Player One Name"); GridBagConstraints conPlayerOneL = new GridBagConstraints(); conPlayerOneL.fill = GridBagConstraints.HORIZONTAL; conPlayerOneL.gridy = 0; conPlayerOneL.gridx = 0; playerOneSetUp.add(playerOneL, conPlayerOneL); playerOneTF = new JTextField(); GridBagConstraints conPlayerOneTF = new GridBagConstraints(); conPlayerOneTF.fill = GridBagConstraints.HORIZONTAL; conPlayerOneTF.gridy = 1; conPlayerOneTF.gridx = 0; playerOneSetUp.add(playerOneTF, conPlayerOneTF); JButton playerOneJColorChooser = new JButton("Player One Color"); GridBagConstraints conPlayerOneJColorChooser = new GridBagConstraints(); conPlayerOneJColorChooser.fill = GridBagConstraints.HORIZONTAL; conPlayerOneJColorChooser.gridy = 2; conPlayerOneJColorChooser.gridx = 0; playerOneSetUp.add(playerOneJColorChooser, conPlayerOneJColorChooser); newGamePanel.add(playerOneSetUp, conPlayerOneSetUp); //adding newGamePanel components JPanel playerTwoSetUp = new JPanel(new GridBagLayout()); GridBagConstraints conPlayerTwoSetUp = new GridBagConstraints(); conPlayerTwoSetUp.fill = GridBagConstraints.BOTH; conPlayerTwoSetUp.gridy = 1; conPlayerTwoSetUp.gridx = 0; JLabel playerTwoL = new JLabel("Player Two Name"); GridBagConstraints conPlayerTwoL = new GridBagConstraints(); conPlayerTwoL.fill = GridBagConstraints.HORIZONTAL; conPlayerTwoL.gridy = 0; conPlayerTwoL.gridx = 0; playerTwoSetUp.add(playerTwoL, conPlayerTwoL); playerTwoTF = new JTextField(); GridBagConstraints conPlayerTwoTF = new GridBagConstraints(); conPlayerTwoTF.fill = GridBagConstraints.HORIZONTAL; conPlayerTwoTF.gridy = 1; conPlayerTwoTF.gridx = 0; playerTwoSetUp.add(playerTwoTF, conPlayerTwoTF); JButton playerTwoJColorChooser = new JButton("Player Two Color"); GridBagConstraints conPlayerTwoJColorChooser = new GridBagConstraints(); conPlayerTwoJColorChooser.fill = GridBagConstraints.HORIZONTAL; conPlayerTwoJColorChooser.gridy = 2; conPlayerTwoJColorChooser.gridx = 0; playerTwoSetUp.add(playerTwoJColorChooser, conPlayerTwoJColorChooser); newGamePanel.add(playerTwoSetUp, conPlayerTwoSetUp); //adding newGamePanel components JPanel options = new JPanel(new GridBagLayout()); GridBagConstraints conOptions = new GridBagConstraints(); conOptions.fill = GridBagConstraints.BOTH; conOptions.gridy = 0; conOptions.gridx = 1; JLabel optionsL = new JLabel("Game Options"); GridBagConstraints conOptionsL = new GridBagConstraints(); conOptionsL.fill = GridBagConstraints.HORIZONTAL; conOptionsL.gridy = 0; conOptionsL.gridx = 0; options.add(optionsL, conOptionsL); unlimitedAmmoCB = new JCheckBox("Unlimited Ammunition"); GridBagConstraints conUnlimitedAmmoCB = new GridBagConstraints(); conUnlimitedAmmoCB.fill = GridBagConstraints.HORIZONTAL; conUnlimitedAmmoCB.gridy = 1; conUnlimitedAmmoCB.gridx = 0; options.add(unlimitedAmmoCB, conUnlimitedAmmoCB); unlimitedTimeCB = new JCheckBox("Unlimited Time"); GridBagConstraints conUnlimitedTimeCB = new GridBagConstraints(); conUnlimitedTimeCB.fill = GridBagConstraints.HORIZONTAL; conUnlimitedTimeCB.gridy = 2; conUnlimitedTimeCB.gridx = 0; options.add(unlimitedTimeCB, conUnlimitedTimeCB); newGamePanel.add(options, conOptions); //adding newGamePanel components JButton startGameB = new JButton("START"); GridBagConstraints conStartGameB = new GridBagConstraints(); conStartGameB.fill = GridBagConstraints.BOTH; conStartGameB.gridy = 1; conStartGameB.gridx = 1; newGamePanel.add(startGameB, conStartGameB); //adding newGamePanel components add(newGamePanel, "newGamePanel"); //newGamePanel is added to higher level display JPanel } } 返回一个LayoutManager而不是实际的LayoutManager ...?)

缩短相关代码

坦克展示

package Tanks;
import javax.swing.*;
import java.awt.*;
public class TankApplication extends JFrame{  
    public static void main (String args[]){    
        TankApplication GUI = new TankApplication();             
    }

    public TankApplication(){
        super("Tanks");
        add(new TankDisplay(this));
        setSize(800, 600);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }
}

坦克申请

package Tanks;
import java.awt.*;
import java.awt.event.*;

import javax.swing.JColorChooser;
public class TankEvent implements ActionListener{

    TankApplication game;
    TankDisplay display;

    public TankEvent(TankDisplay d, TankApplication g){ //I found this was necesarry because I didn't want to call the constructors of panels
        display = d;                                    //and frames. I'm not sure why that caused errors, but it does. And when I tried to
        game = g;                                       //create overloaded constructors for TankApplication and TankDisplay, their references
    }                                                   //didn't have the information I needed. This is likely because I kept most of the components
                                                        //as local variables in the constructors, instead of creating variables in their respective classes, and using 
    public void actionPerformed(ActionEvent e){         //the constructors to modify them
        CardLayout layOut = (CardLayout)(display.getLayout()); //<---Why do I need to do this?
        switch(e.getActionCommand()){
            case "New Game":
                layOut.show(display, "newGamePanel");
                game.pack();    //<<<---Root problem. Sometimes newGamePanel is packed, the JFrame is smaller, sometimes newGameaPanel is not packed. Seems random
                game.setResizable(false); //for this JPanel only, I don't want to be able to resize the window. I will change this when the user flips
                break;                    //to another JPanel       
        }
    }
}

坦克赛事

  let g:syntastic_python_flake8_exec = '/path/to/python3'
罗伯特好像问similar question,但似乎没有得到满意的答案。为什么线程与此有关?

1 个答案:

答案 0 :(得分:1)

您没有正确使用CardLayout

在面板上使用CardLayout时,面板的首选大小是添加到CardLayout的最大子面板的大小。

从一个面板交换到另一个面板不会改变面板的首选尺寸,因此也不会改变框架的尺寸。所以pack()方法没有效果。

我建议你不要担心包装框架。只需创建&#34;菜单面板&#34;以便它的组件居中。然后,当你开始游戏时,所有改变的是你显示&#34;游戏面板&#34;。