拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 GridLayout表现出奇怪的行为

GridLayout表现出奇怪的行为

白鹭 - 2022-01-23 1938 0 0

我正在尝试创建一个由 100 个正方形组成的网格。我下面的代码非常错误,我不知道为什么。

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;

public class snake extends JFrame
{
    public static void main(String[] args)
    {
        Border whiteLine = BorderFactory.createLineBorder(Color.white);
        //-----------FRAME
        JFrame frame = new JFrame();
        frame.setSize(1000,1000);
        frame.setTitle("Snake");
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.getContentPane().setBackground(Color.black);
        frame.setVisible(true);
        frame.setLayout(new GridLayout(10,10));
        //-----------FRAME

        //-----------PANELS
        Dimension panelDimension = new Dimension(20,20);

        int counter = 0;
        JPanel[][] p = new JPanel[10][10];
        for (int i = 0; i < 10; i  )
        {
            for (int j = 0; j < 10; j  )
            {
                p[i][j] = new JPanel();
                //p[i][j].setPreferredSize(panelDimension);
                p[i][j].setBackground(Color.red);
                //p[i][j].setLocation(490,490);
                p[i][j].setBorder(whiteLine);
                p[i][j].setVisible(true);

                frame.getContentPane().add(p[i][j]);

                counter =1;
            }
        }
       System.out.println("counter: "   counter);


    }
}

当我运行这样的代码时,它显示了一个由 2 列组成的网格,第一列有 7 行,第二列有 6 行。有时它甚至显示其他不正确的列数和行数。我不知道为什么它不创建一个 10 行 10 列的网格。

uj5u.com热心网友回复:

你有几个问题,包括:

  • 呼叫setVisible(true)上的JFrame之前添加组件,称之前pack()的顶层视窗。这可能会导致我们的 GUI 中的定位组件不稳定,甚至 GUI 仍然为空
  • pack()添加组件后和设定可见之前不呼叫JFrame
  • 设定 JFrame 的大小。让布局管理器、容器和组件为您执行此操作(这就是呼叫的pack()目的)
  • 将其设定为错误的大小,一个“完美的正方形”,忽略作业系统添加的选单栏,
  • ...

例如:

package foo01;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class SnakePanel extends JPanel {
    private static final int CELL_WIDTH = 80;
    private static final Dimension CELL_DIMENSION = new Dimension(CELL_WIDTH, CELL_WIDTH);
    private static final int COLUMNS = 10;
    private static final int GAP = 2;
    private static final Color BG_COLOR = Color.WHITE;
    private static final Color CELL_COLOR = Color.RED;

    public SnakePanel() {
        setBackground(BG_COLOR);
        
        // add a white line around the grid
        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        
        // create a grid with gaps that show the background (white) color
        setLayout(new GridLayout(COLUMNS, COLUMNS, GAP, GAP));

        for (int row = 0; row < COLUMNS; row  ) {
            for (int col = 0; col < COLUMNS; col  ) {
                JPanel cell = new JPanel(); // create a new cell
                cell.setPreferredSize(CELL_DIMENSION); // cheating here. Better to override getPreferredSize()
                cell.setBackground(CELL_COLOR);
                add(cell);
                
                // give the cell JPanel some simple behavior:
                cell.addMouseListener(new MyMouse(col, row));
            }
        }
    }

    private class MyMouse extends MouseAdapter {
        private int col;
        private int row;

        public MyMouse(int col, int row) {
            this.col = col;
            this.row = row;
        }
        
        @Override
        public void mousePressed(MouseEvent e) {
            System.out.printf("Mouse pressed row and column: [%d, %d]%n", row, col);
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            // create the main JPanel
            SnakePanel snakePanel = new SnakePanel();

            // create the JFrame
            JFrame frame = new JFrame("Snake");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            // add the main JPanel to the JFrame
            frame.add(snakePanel);
            
            // pack the JFrame -- tells the layout managers to do their things
            frame.pack();
            
            // if we want to center the GUI:
            frame.setLocationRelativeTo(null);
            
            // only *now* do we display the GUI
            frame.setVisible(true);
        });
    }
}

关于代码的一些注释:

传递给SwingUtilities.invokeLater(...)方法的 Runnable 中的任何代码都会在Swing 事件执行绪上呼叫,这在创建 Swing GUI 时是明智的做法

SwingUtilities.invokeLater(() -> {
    // ....
});

首先,创建由 JFrame 保存的主 JPanel:

SnakePanel snakePanel = new SnakePanel();

然后创建 JFrame,添加 JPanel 并呼叫pack(). pack 呼叫告诉布局管理器在那里做一些事情,在容器中布局组件,根据他们的首选大小和布局来调整大小:

JFrame frame = new JFrame("Snake");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(snakePanel);
frame.pack();

如果我们想让 GUI 居中:

frame.setLocationRelativeTo(null);

只是现在我们显示GUI

frame.setVisible(true);
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *