问题
多次编译并运行我的程序后,有时候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
重新绘制了JFrames
(JFrame
甚至重新绘制了?也许是重新验证/更新?)。但只要我在完成时重置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,但似乎没有得到满意的答案。为什么线程与此有关?
答案 0 :(得分:1)
您没有正确使用CardLayout
。
在面板上使用CardLayout
时,面板的首选大小是添加到CardLayout的最大子面板的大小。
从一个面板交换到另一个面板不会改变面板的首选尺寸,因此也不会改变框架的尺寸。所以pack()方法没有效果。
我建议你不要担心包装框架。只需创建&#34;菜单面板&#34;以便它的组件居中。然后,当你开始游戏时,所有改变的是你显示&#34;游戏面板&#34;。