2

私には本当に単純な問題であるべきだと思われるものがあります。私の意見では、それは作成した人々の大規模な見落としにすぎませGridBagLayoutん...

ともかく。私GridBagLayoutが作っているゲームのタイルの 27x13 グリッドを表示するために使用しています。コンポーネントのサイズを変更できることと、構成が非常に簡単であることから、このレイアウトを使用しましたが、1 つだけ小さな問題があります。タイルのサイズを変更するときに、幅が 27 の倍数でない場合、または高さが 13 の倍数でない場合、境界線の周りに空白が配置されます。

私が何を意味するかを示すために:

フレームのサイズを 864x416 (27 と 13 の完全な倍数) になるようにサイズ変更すると、次のようになりますJPanel

フレームのサイズを 863x415 に変更するとJPanel 27 や 13 の倍数にはなりません。

余分なピクセルをタイル間で分配していないだけです。どうしてか分かりません。それぞれのメソッドを使用したり、それらをオーバーライドしたり、または制約を使用したりして、最小/最大/優先サイズをいじると、GridBagLayout空白ipadxipady削除できますが、残りの部分に合わせて最も外側のタイルを押しつぶすだけです。これは、以下のコード例で確認できます。

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());
    }
}

私の質問は、レイアウトを常に最初の画像のように見せるにはどうすればよいですか? 別のレイアウトが必要ですか? 私はここでとても迷っています。

4

1 に答える 1

2

正方形のタイルのあるパネルにはGridLayoutを使用し、ウィンドウの残りの部分には別のレイアウト(GridBagLayout、BorderLayout、BoxLayout、またはレイアウトの組み合わせ)の中にネストします。

そうは言っても、この場合、GridLayoutとGridBagLayoutの両方がピクセルを均等に分散します。ピクセル全体しか使用できないため、スペースを分割した後、余りが残り、それがパディングとして使用されます。いくつかの潜在的な回避策がありますが、これは主に避けられません。

  • 特定のウィンドウサイズを適用する
  • 必要以上に大きなパネルを描画しますが、ビューポートを使用して、ビューで余分なタイルが切り捨てられるようにします
  • タイル領域に隣接する他の要素を追加して、余分なパディングがあるという事実を効果的に隠します

最初のオプションで問題がない場合は、ウィンドウを互換性のあるサイズにスナップするように少し変更して、余りがないようにすることができます(注:ハードコードされたintのいくつかを定数に変更しました)。

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());
        }
}
于 2012-12-15T23:18:08.583 に答える