2016-11-26 22 views
0

問題包方法從的actionPerformed函數調用只是有時

在編譯和運行我的程序多次,有時pack()作品和newGamePanel組件被壓縮,有時不工作,newGamePanel展開以填充由setSize()設置的值JFrame。我一直無法可靠地重現任何一個結果 - 它確實似乎是隨機的。

注:因爲我減少了GUI格式的數量以便有合理數量的代碼進行審閱,所以GUI非常垃圾。但是,這個問題仍然很容易識別。當應該打包的JPanel顯示爲CardLayout時,有時JFrame是「打包」大小,有時它與我在開始時設置的setSize()值相匹配。現在我切割了GUI,newGamePanel組件不會移動以填充它們的容器,但那是因爲我刪除了它們的所有約束值。

猜疑和設計

我從TankEvent類,它實現ActionListener調用pack()。遊戲是在TankEvent的構造函數中傳遞給TankEvent的對象(TankApplication對象(TankApplication擴展JFrame),該構造函數被TankDisplayTankDisplay擴展爲JPanel)調用。

JFrame實例化JPanel,傳遞自我的實例。 JPanel實例化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  
     } 
    } 
} 

羅伯特似乎已經問過similar question,但似乎沒有得到滿意的答案。爲什麼線程與此有關?

+0

*「相關代碼:」*代碼問題實際上通常在應用程序的完全不同的部分。比我們預期的要高。爲了儘快提供更好的幫助,請發佈[MCVE]或[簡短,獨立,正確的示例](http://www.sscce.org/)。 –

+0

我閱讀了這兩篇文章,但讓我驗證一下。基本上,我需要削減我的代碼中的所有內容,我不需要重現該問題。這不僅會幫助我隔離問題,而且會爲每個人提供可管理數量的代碼來查看? – ulw1

+0

我做了編輯。我很確定這是一個MCV。 – ulw1

回答

1

您沒有正確使用CardLayout

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

從一個面板交換到另一個面板不會改變面板的首選尺寸,從而改變框架。所以pack()方法將不起作用。

我建議你不要擔心打包框架。只需創建「菜單面板」,使其組件居中。然後,當你開始遊戲時,所有變化就是你顯示「遊戲面板」。

+0

這是一個很好的解決方案,但我不確定它回答了爲什麼pack()有時起作用,有時不起作用的問題。我現在明白了爲什麼它不起作用,但pack()不起作用,因爲它有時會改變幀的大小。 – ulw1

+0

@ ulw1,就像我說你沒有發佈正確的'MCVE',所以我不能測試你的代碼,試圖瞭解你在做什麼。 – camickr

相關問題