2017-04-05 69 views
-1

我遇到了一个JPanel问题,我不知道发生了什么。所以我有一个带有init函数的JFrame,它创建了一个名为GamePanel的自定义JPanel,奇怪的是它始终不会在paintComponents函数中执行,即使我在对象上使用了重绘。Java Swing JPanel paintComponents never called

这里是我的代码时,我初始化的JPanel(在一个JFrame):

this.gamePanel = new GamePanel(this.grid, this); 
this.panel.add(this.gamePanel, constraints); 

而且JPanel的本身:

public class GamePanel extends JPanel { 

    private final int SQUARE_SIZE = 50; 

    private Grid grid; 
    private final GameView gameView; 

    public GamePanel(Grid grid, GameView gameView) { 
     this.gameView = gameView; 

     this.setPreferredSize(new Dimension(200, 200)); 
    } 

    public void setGrid(Grid grid) { 
     this.grid = grid; 
     this.setPreferredSize(new Dimension(grid.getSizeX() * SQUARE_SIZE, grid.getSizeY() * SQUARE_SIZE)); 
    } 

    @Override 
    public void paintComponents(Graphics g) { 
     System.out.println("test"); 

     if (this.grid != null) { 

      Graphics2D g2 = (Graphics2D) g; 

      double thickness = 3; 
      g2.setStroke(new BasicStroke((float) thickness)); 

      g2.setColor(Color.BLACK); 

      for (int i = 0; i < 3; i++) { 
       for (int j = 0; j < 3; j++) { 
        int x = SQUARE_SIZE * i; 
        int y = SQUARE_SIZE * j; 

        g2.drawRect(x, y, SQUARE_SIZE, SQUARE_SIZE); 

        if(this.grid.getSquareState(x, y) != 0) { 
         char[] tmp = ("" + this.grid.getSquareState(x, y)).toCharArray(); 
         g2.drawChars(tmp, 0, 1, x, y); 
        } 
       } 
      } 
     } 
    } 
} 

编辑:(整个的JFrame)

public class GameView extends JFrame { 

    private CustomSocket socket; 
    private JPanel panel; 
    private GamePanel gamePanel; 
    private JLabel listPlayers; 
    private JLabel playerPlaying; 
    private Grid grid; 

    public GameView(CustomSocket socket) { 
     this.socket = socket; 
     this.setTitle("TicTacToe - Client"); 

     this.setSize(600, 480); 

     this.setLocationRelativeTo(null); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     this.init(); 
     this.pack(); 
     this.setVisible(true); 
     this.play(); 
    } 

    private void init() { 
     this.panel = new JPanel(); 
     this.panel.setLayout(new GridBagLayout()); 

     GridBagConstraints constraints =new GridBagConstraints(); 
     constraints.fill = GridBagConstraints.CENTER; 

     constraints.gridx = 0; 
     constraints.gridy = 0; 
     constraints.gridwidth = 1; 

     // Grid 
     this.gamePanel = new GamePanel(this.grid, this); 
     this.panel.add(this.gamePanel, constraints); 

     // Labels 
     constraints.gridy += 1; 
     this.listPlayers = new JLabel(); 
     this.panel.add(this.listPlayers, constraints); 

     constraints.gridy += 1; 
     this.playerPlaying = new JLabel(); 
     this.panel.add(this.playerPlaying, constraints); 

     this.setContentPane(this.panel); 
    } 

    private void play() { 
     String[] tmp = this.socket.getData().split(";"); 

     this.grid = new Grid(Integer.parseInt(tmp[0]), Integer.parseInt(tmp[1])); 

     String players = ""; 
     for(int i = 2; i < tmp.length; i++) { 
      players += tmp[i] + " "; 
     } 

     this.listPlayers.setText(players); 

     boolean notFinished = true; 
     while(notFinished) { 
      String[] gridData = this.socket.getData().split(";"); 
      for(int i = 1; i < gridData.length; i++) { 
       String[] gridRow = gridData[i].replace("(", "").replace(")", "").split(","); 


       for(int j = 0; j < gridRow.length; j++) { 
        this.grid.setSquareState(i - 1, j, Integer.parseInt(gridRow[j])); 
       } 
      } 

      this.gamePanel.repaint(); 

      String playerPlaying = this.socket.getData().split(";")[0]; 

      if(playerPlaying != this.socket.getUsername()) { 
      } 
      notFinished = true; 
     } 
    } 
} 

预先感谢您。

+2

使用paintComponent而不是paintComponents – ControlAltDel

+0

我尝试过这两个函数,不幸的是它不起作用 –

+0

为什么它是你的[7问题](http://stackoverflow.com/users/6743005/florian-merle),只有**一个**有一个可接受的答案?所以没有为你工作? –

回答

2
this.panel.add(this.gamePanel, constraints); 

您将组件添加到面板,但面板没有首选大小。由于它的大小是(0,0),因此没有任何内容可以绘制,因此该方法从不会被调用。

所有Swing组件负责确定自己喜欢的大小。覆盖您的自定义组件的getPreferredSize()方法。然后布局管理器可以设置组件的正确大小/位置。

paintComponent(...)是重写的正确方法,不要忘记super.paintComponent(...)作为确保背景被清除的第一条语句。

+0

好吧,添加getPreferredSize()方法并没有解决问题,但如果我更改了维度,它会使窗口变大。 –

+0

编辑:我在原来的文章中添加了JFrame的全部代码 –

+0

@FlorianMerle你错过了我的最后一点,现在已经做了两次。另外,谁知道你的Socket是否会导致问题。也许代码阻塞等待输入。做更多的调试来确定逻辑流程是否正确。 – camickr