有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

有时仅从actionPerformed函数调用java包方法

问题

在多次编译和运行我的程序时,有时pack()可以工作,newGamePanel的组件被压缩,有时它不工作,newGamePanel扩展以填充setSize()设置的JFrame值。我无法可靠地再现这两种结果——它看起来确实是随机的

注意:由于我减少了GUI格式化的数量,以便有合理数量的代码进行审查,GUI是相当垃圾的。然而,问题仍然很容易识别。当应该打包的JPanel显示为CardLayout时,有时JFrame是“打包”大小,有时它与我在开始时设置的setSize()值匹配。现在我剪切了GUI,newGamePanel组件不会移动来填充它们的容器,但这只是因为我删除了它们的所有约束值

怀疑与设计

我从类TankEvent调用pack(),该类实现了ActionListener。Game是传递给TankEvent构造函数中的TankEventTankApplication对象(TankApplication扩展JFrame),它被TankDisplayTankDisplay扩展JPanel调用

JFrame实例化JPanel,传递self的实例。 JPanel实例化ActionListener,传递self的实例。 ActionListener使用pack()修改JFrame

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

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。这是docs.oracle中建议的实现,但为什么getLayout()返回的是LayoutManager而不是实际的LayoutManager…?)

缩短相关代码

坦克显示器

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

    }
}

油罐应用

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

罗伯特似乎问了个问题,但似乎没有得到满意的答案。为什么线程与此有关


共 (1) 个答案

  1. # 1 楼答案

    您没有正确使用CardLayout

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

    从一个面板切换到另一个面板不会改变面板的首选尺寸,因此也不会改变框架。因此,pack()方法将无效

    我建议你不要担心包装框架。只需创建“菜单面板”,使其组件居中即可。当你开始游戏时,所有的变化就是你显示“游戏面板”