2012-12-15 71 views
2

我對我而言似乎應該是一個非常簡單的問題。在我看來,這只是對GridBagLayout ...GridBagLayout不會正確地在組件之間分配尺寸

的人的大規模監督。我正在使用GridBagLayout爲我正在製作的遊戲顯示27x13的網格。我使用這種佈局是因爲它能夠調整組件的大小,並且因爲配置有多容易,但這只是一個小問題。如果寬度不是27的倍數,或者如果高度不是13的倍數,則會在邊界周圍放置空白區域。

爲了說明我的意思:

Here是個什麼樣子,當我調整框架等,以使該JPanel內的大小864x416,27完美的倍數和13

Here是個什麼樣子就像當我調整框架的大小,使JPanel大小爲863x415,只是幾乎不是27或13的倍數。

它只是不在瓦片中分配額外的像素。我不知道爲什麼。當我用他們各自的方法擺弄最小/最大/首選大小,或者甚至使用GridBagLayoutipadxipady限制時,我可以刪除空白區 - 但它只是擠壓最外面的瓷磚以適應休息。你可以在下面的示例代碼中看到它。

下面是一個SSCCE:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.util.Random; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Game extends JPanel { 
    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       start(); 
      } 
     }); 
    } 
    static void start() { 
     JFrame frame = new JFrame("Game"); 
     JPanel newFrame = new MainGameScreen(); 
     frame.getContentPane().add(newFrame); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 
class MainGameScreen extends JPanel { 
    public MainGameScreen() { 
     setPreferredSize(new Dimension(864, 551)); 
     setLayout(new GridBagLayout()); 
     setBackground(Color.green); 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.fill = GridBagConstraints.BOTH; 
     gbc.weightx = 1; 
     gbc.weighty = 1; 
     gbc.ipadx = 0; //Change to 64 to see undesired effects 
     gbc.ipady = 0; //^ 
     for (int i=0;i<13;i++) { 
      for (int j=0;j<27;j++) { 
       gbc.gridx = j; 
       gbc.gridy = i; 
       add(new ImagePanel(), gbc); 
      } 
     } 
    } 
} 
class ImagePanel extends JComponent { 
    private int r,g,b; 
    public ImagePanel() { 
     Random generator = new Random(); 
     r = generator.nextInt(100)+1; 
     g = generator.nextInt(100)+1; 
     b = generator.nextInt(100)+1; 
    } 
    @Override 
    public void paintComponent(Graphics gr) { 
     super.paintComponent(gr); 
     gr.setColor(new Color(r,g,b)); 
     gr.fillRect(0, 0, getWidth(), getHeight()); 
    } 
} 

我的問題是,如何才能讓佈局不斷看起來像第一個形象呢?我需要不同的佈局嗎?我很迷茫。

+0

有點偏離主題,但我會建議不要使用'GridBagLayout',除非你絕對必須。這只是市長頭痛的IMO - 大部分相同的功能可以通過BoxLayout實現。 –

+0

由於每個瓷磚的重量與其他瓷磚的重量完全相同,並且由於像素不能在亞像素中切割,所以佈局應如何平均分配27個部件中的像素? –

+0

@JBNizet - 我希望它會在行中增加一個像素的寬度,直到它沒有更多的可用空間。它看起來非常基本,不會影響它的外觀。假設它有25個免費像素,它向左推到右邊。爲什麼不能在該行中添加一個像素寬度爲25個圖塊? – Keter

回答

2

我將爲具有正方形貼圖的面板使用GridLayout,並將其嵌套到另一個佈局(GridBagLayout,BorderLayout,BoxLayout或某些佈局組合)中。

這就是說,GridLayout和GridBagLayout將在這種情況下均勻分佈像素。由於您只能使用整個像素,所以在分割空間後剩餘的餘數將用作填充。這在很大程度上是不可避免的,雖然有一些可能的解決辦法:

  • 執行某些窗口大小
  • 畫一個更大的面板比你需要的,但使用一個視口,以便多餘的瓷磚在視圖中截斷
  • 添加接壤的平鋪面積,有效地隱瞞事實,有微胖

如果您能夠接受的第一個選項等元素,你可以做一個稍微修改到窗口捕捉到兼容的尺寸,使得存在是沒有剩餘的(注:我也改變了d幾個你的硬編碼整數常量):

package com.example.game; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import java.util.Random; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

    public class Game extends JPanel {  
     public static void main(String[] args) { 
      javax.swing.SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        start(); 
       } 
      }); 
     } 

     static void start() { 
      final JFrame frame = new JFrame("Game"); 
      JPanel newFrame = new MainGameScreen(); 

      frame.addComponentListener(new ComponentAdapter() { 
       @Override 
       public void componentResized(ComponentEvent e) { 
        int h = frame.getContentPane().getHeight() % MainGameScreen.ROWS; 
        int w = frame.getContentPane().getWidth() % MainGameScreen.COLS; 

        // Subtract the remainder pixels from the size. 
        frame.setSize(frame.getWidth() - w, frame.getHeight() - h); 
       } 
      }); 
      frame.getContentPane().add(newFrame); 
      frame.pack(); 
      frame.setLocationRelativeTo(null); 
      frame.setVisible(true); 
     } 
    } 
    class MainGameScreen extends JPanel { 
     static final int ROWS = 13; 
     static final int COLS = 27; 

     public MainGameScreen() { 
      setPreferredSize(new Dimension(864, 551)); 
      setLayout(new GridBagLayout()); 
      setBackground(Color.green); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.fill = GridBagConstraints.BOTH; 
      gbc.weightx = 1; 
      gbc.weighty = 1; 
      gbc.ipadx = 0; //Change to 64 to see undesired effects 
      gbc.ipady = 0; //^ 
      for (int i=0;i<ROWS;i++) { 
       for (int j=0;j<COLS;j++) { 
        gbc.gridx = j; 
        gbc.gridy = i; 
        add(new ImagePanel(), gbc); 
       } 
      } 
     } 
    } 

    class ImagePanel extends JComponent { 
     private int r,g,b; 
     public ImagePanel() { 
      Random generator = new Random(); 
      r = generator.nextInt(100)+1; 
      g = generator.nextInt(100)+1; 
      b = generator.nextInt(100)+1; 
     } 
     @Override 
     public void paintComponent(Graphics gr) { 
      super.paintComponent(gr); 
      gr.setColor(new Color(r,g,b)); 
      gr.fillRect(0, 0, getWidth(), getHeight()); 
     } 
}