仅从actionPerformed函数调用的Pack方法 [英] Pack method called from actionPerformed functions only sometimes

查看:158
本文介绍了仅从actionPerformed函数调用的Pack方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

Problem

在多次编译和运行程序时,有时pack()可以工作,并且newGamePanel的组件被压缩,有时不起作用,并且newGamePanel可以扩展以填充setSize().我无法可靠地重现任何一个结果-似乎确实是随机的.

Upon compiling and running my program multiple times, sometimes pack() works and the components of newGamePanel are compressed, and sometimes it doesn't work, and newGamePanel expands to fill the JFrame values set by setSize(). I have been unable to reliably reproduce either result-- it really seems to be random.

注意:由于我减少了GUI格式的数量,以减少代码量,因此GUI非常浪费.但是,问题仍然很容易识别.当CardLayout显示应该打包的JPanel时,有时JFrame是打包"大小,有时它匹配我一开始设置的setSize()值.既然我已经切断了GUI,newGamePanel组件就不会移动以填充其容器,但这只是因为我删除了所有约束值.

Note: As I cut down on the amount of GUI formatting to have a reasonable amount of code to review, the GUI is pretty trash. However, the problem is still easy to identify. When the JPanel that's supposed to be packed is shown by CardLayout, sometimes the JFrame is the "packed" size and sometimes it matches the setSize() values I set in the beginning. Now that I cut the GUI, the newGamePanel components don't move to fill their container, but that's just because I removed all their constraint values.

怀疑与设计

我正在从实现ActionListener的类TankEvent调用pack().游戏是在TankEvent构造函数中传递给TankEventTankApplication对象(TankApplication扩展JFrame),由TankDisplay调用(TankDisplay扩展JPanel).

I am calling pack() from class TankEvent, which implements ActionListener. Game is a TankApplication object (TankApplication extends JFrame) passed to TankEvent in the TankEvent constructor, which is called by TankDisplay (TankDisplay extends JPanel).

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

JFrame instantiates JPanel, passes instance of self. JPanel instantiates ActionListener, passes instance of self. ActionListener modifies JFrame using pack().

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

The following is the code executed when a button is pressed.

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的大小,我就不确定为什么会出现问题.

I wonder if the issue is in my design. I'm making a huge assumption that pack() repaints the JFrame (are JFrames even repainted? Perhaps revalidates/updates?). But as long as I reset the size of JFrame when I'm done, I'm not sure why it would be an issue..

(侧面问题,我不确定为什么需要将display.getLayout()强制转换为CardLayout.这是docs.oracle中建议的实现,但是为什么getLayout()返回LayoutManager而不是实际的LayoutManager ...?)

(Side question, I'm not sure why I need to cast display.getLayout() as a CardLayout. This is the suggested implementation from docs.oracle, but why does getLayout() return a LayoutManager and not the actual 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       
        }
    }
}

Robert似乎问了一个类似问题,但没有似乎得到了满意的答案.为什么线程与此有关?

Robert seems to have asked a similar question, but didn't seem to get a satisfactory answer. Why do threads have anything to do with this?

推荐答案

您没有正确使用CardLayout.

在面板上使用CardLayout时,首选的面板尺寸是添加到CardLayout中的最大子面板的尺寸.

When you use a CardLayout on a panel the preferred size of the panel is the size of the largest child panel added to the CardLayout.

从一个面板切换到另一个面板不会改变面板的首选大小,因此不会更改框架.因此pack()方法将无效.

Swapping from one panel to another will not alter the preferred size of panel and therefore the frame. So the pack() method will have no effect.

我建议您不要担心包装框架.只需创建菜单面板",使其组件居中.然后,当您启动游戏时,所有更改就是显示游戏面板".

I suggest you don't worry about packing the frame. Just create the "menu panel" so that its components are centered. Then when you start the game all that changes is that you display the "game panel".

这篇关于仅从actionPerformed函数调用的Pack方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆