【问题标题】:How to Create JPanels in a Loop and insert them in JPanel Array [] []如何在循环中创建 JPanel 并将它们插入 JPanel Array [] []
【发布时间】:2019-12-11 12:27:55
【问题描述】:

大家好,我正在使用 Eclipse,我正在尝试创建一个 Connect4 Game Grid ,它是一个 JPanel gridArray [6] [7]。我稍后将按钮和网格的不同面板添加到主面板中,并将其添加到我的框架中。

我的问题: 我想用一个空字段(白色)的图片填充 gridArray JPanel,但首先我想创建一个新面板并通过循环将其插入到我的 gridArray 中,直到 gridArray 里面有所有 42 个面板并完全填充。我在下面有我的代码,但不知何故它不起作用,尽管我的逻辑应该没问题。

我尝试使用辅助函数创建一个新的 JPanel,并在 fillGrid(); 中为每个循环调用该函数,基本上调用了 42 次,但它仍然无法工作......

我将很高兴得到一些帮助!

package connect4;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class GridTest extends JFrame {

    JFrame mainWindow;
    JPanel buttonPanel, mainPanel;
    JPanel gridPanel;
    JPanel emptyPanel;
    JPanel panel1;
    ImageIcon emptyBox;
    JPanel[][] gridArray;

    JLabel emptyLabel;

    JButton arrow1,arrow2,arrow3,arrow4,arrow5,arrow6,arrow7;

    public GridTest() {
        createGameGrid();
        fillGrid();
    }

    public void createGameGrid() {

        //creating window and mainpanel
        mainWindow = new JFrame("Connect 4");
        mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());

        //defining top panel with 7 buttons;
        buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(1, 7));

        arrow1 = new JButton("V");
        arrow2 = new JButton("V");
        arrow3 = new JButton("V");
        arrow4 = new JButton("V");
        arrow5 = new JButton("V");
        arrow6 = new JButton("V");
        arrow7 = new JButton("V");

        buttonPanel.add(arrow1);
        buttonPanel.add(arrow2);
        buttonPanel.add(arrow3);
        buttonPanel.add(arrow4);
        buttonPanel.add(arrow5);
        buttonPanel.add(arrow6);
        buttonPanel.add(arrow7);

        //create Grind Panel
        gridPanel = new JPanel();
        gridPanel.setLayout(new GridLayout(6,7));

        mainPanel.add(buttonPanel, BorderLayout.NORTH);
        mainPanel.add(gridPanel, BorderLayout.SOUTH);
        mainWindow.add(mainPanel);
        mainWindow.pack();
        mainWindow.setLocationRelativeTo(null);
        mainWindow.setVisible(true);
    }

    private JPanel greateOnePanel(){
      //here we need to insert the icon which is in empty box into a newly created panel   
      //ifirst wanted to insert black panels do ensure it works as intended but it doesnt
        JPanel panel = new JPanel();
        panel.setBackground(Color.BLACK);
        panel.setSize(50,50);

        return panel;
    }

    //here we need to fill the grid with the panels created above from left to right...
    public void fillGrid() {
       for(int j = 0; j < 6; j++) {
          for (int k = 0; k < 7; k++) {
            gridPanel.add(greateOnePanel());

          }
       }
    }

   public static void main(String[] args) {
     new GridTest();
   }
}

我使用 gridArray 尝试了这种方法,但它会抛出 NullPointer Exeptions 并且不会用简单的文本标签“Hallo”填充网格(仅用于测试目的)

public void fillGrid() {
        for(int j = 0; j < 6; j++) {
          for (int k = 0; k < 7; k++) {

             JLabel label = new JLabel("Hallo"); 

            gridArray[j][k] = new JPanel();
            gridArray[j][k].setSize(50, 50);
            gridArray[j][k].setBackground(Color.RED);
            gridArray[j][k].add(label);
            gridPanel.add(gridArray[j][k]);


          }
        }
    }

【问题讨论】:

  • 我不是专家,但有 42 个面板.. 你确定这是最好的解决方案吗? Afaik 你应该只需要一个 JPanel。
  • 我想使用 ImageIcon,将其插入到面板中,然后将面板插入到我的 gridArray 面板中。
  • 你快到了,使用 LayoutManager,比如 BorderLayout。 (j, k) 作为参数来确定图像。
  • @JoopEggen,我明白你的想法,但首先我想用空的黑色面板填充它。知道为什么它不起作用吗?
  • 试试setPreferredSize(50, 50) 和更好的mainPanel.add(gridPanel, BorderLayout.CENTER);

标签: java arrays swing jframe jpanel


【解决方案1】:

这是一个简短的、自包含的代码,应该有助于完成任务的各个方面。

不需要在每个单元格中设置面板。它唯一有帮助的是设置 BG 颜色。只要背景设置为不透明,就可以在标签中完成。

这段代码定义了一个SquareLabel 覆盖getPreferredSize() 以返回首选宽度和高度的最大值作为两者的值(通常是宽度)。

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

public class SquareLabelGrid {

    int rows = 6;
    int cols = 7;
    JLabel[][] labelArray = new JLabel[cols][rows];
    Font bigFont = new Font(Font.SANS_SERIF, Font.BOLD, 30);
    Insets labelInsets;

    SquareLabelGrid() {
        JPanel gameBoard = new JPanel(new GridLayout(rows, cols));
        // a border to make the cell boundaries more clear and add 
        // some space around the text
        Border border = new CompoundBorder(
                new LineBorder(Color.BLACK),new EmptyBorder(4,4,4,4));
        for (int yy = 0; yy < rows; yy++) {
            for (int xx = 0; xx < cols; xx++) {
                JLabel l = getColoredSquareLabel(xx, yy);
                labelArray[xx][yy] = l;
                gameBoard.add(l);
                l.setBorder(border);
            }
        }
        JOptionPane.showMessageDialog(null, gameBoard);
    }

    private JLabel getColoredSquareLabel(int x, int y) {
        SquareLabel label = new SquareLabel(
                String.format("%1s,%1s", (x+1), (y+1)));
        label.setFont(bigFont);
        label.setOpaque(true); // so we can see the BG color
        label.setBackground(Color.ORANGE); // I prefer orange!
        // make the GUI less 'crowded'
        label.setBorder(new EmptyBorder(4,4,4,4)); 

        return label;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            new SquareLabelGrid();
        };
        SwingUtilities.invokeLater(r);
    }
}

class SquareLabel extends JLabel {

    SquareLabel(String label) {
        super(label);
    }

    /* This will create a square component that accounts for the 
     size of the String / Icon it contains. No guesswork! */
    @Override
    public Dimension getPreferredSize() {
        Dimension d = super.getPreferredSize();
        int w = d.width;
        int h = d.height;
        int sz = w > h ? w : h;

        return new Dimension(sz, sz);
    }
}

【讨论】:

    【解决方案2】:

    问题是你还没有初始化网格数组。 否则会抛出空指针异常。

    JPanel[][] gridArray = new JPanel[6][8];
    

    还可以设置主面板的首选大小以使网格可见。

    mainPanel.setPreferredSize(new Dimension(400, 200));
    

    当我使用此处提到的修改运行您的代码时,我可以看到以下内容。

    另外,请使用以下代码从 main 执行它。

       public static void main(String[] args) {
            //Schedule a job for the event-dispatching thread:
            //creating and showing this application's GUI.
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new GridTest();
                }
            });    
    
       }
    

    【讨论】:

    • “同时设置主面板的首选尺寸以使网格可见” 最好避免使用首选尺寸。如果事实证明有必要(例如使用自定义绘制面板),最好覆盖 getPreferredSize() 并(可能)考虑到父级返回的首选大小。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 2021-08-29
    • 2012-03-25
    • 1970-01-01
    • 2010-10-07
    • 2017-10-13
    • 2012-09-18
    相关资源
    最近更新 更多