ImageIcon的2D数组显示不一致,并且仅在JPanel中部分显示

时间:2019-02-22 03:05:18

标签: java swing multidimensional-array jframe jpanel

我正在尝试使用ImageIcons,JLabels和JPanel创建一个充满16x16地砖的屏幕。我的问题是,每当我尝试使用2D数组显示这些图块时,即使反复循环绘制方法,它们也不会完全显示。相反,它们只显示几个图块,而不是完整的数组。此外,每次我运行该程序时,显示的图块数量都会改变!

这是我正在使用的代码:

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class JFrameTest {

    static BufferedImage buf;
    static JPanel panel;


    public static void main(String[] args) {
        createWindow();
        loadImage();
        showImage();
    }



    public static void createWindow() {
        JFrame frame = new JFrame();
        panel = new JPanel();
        frame.setSize(1000, 1000);
        frame.setTitle("Tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.add(panel);
        frame.setVisible(true);
        panel.setLayout(null);

    }




    public static void loadImage() {
        try {
            buf = ImageIO.read(new File("res/test.png"));
        } catch (IOException ex) {
            System.out.println("NOT FOUND");
        }

    }

    public static void showImage() {

        final int[][] MAP =
                {
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1},
                        {1, 1, 1, 1, 1, 1, 1, 1, 1}
                };

        ImageIcon test = new ImageIcon(buf);

        panel.setBackground(Color.WHITE);
        System.out.println(test.getIconWidth());
        System.out.println(test.getIconHeight());

        JLabel[][] labelGrid = new JLabel[MAP.length][MAP[0].length];

        for (int r = 0; r < labelGrid.length; r++) {
            for (int c = 0; c < labelGrid[r].length; c++) {
                labelGrid[r][c] = new JLabel();
                labelGrid[r][c].setSize(test.getIconWidth(), test.getIconWidth());
                labelGrid[r][c].setLocation(test.getIconWidth() * r, test.getIconHeight() * c);
                labelGrid[r][c].setIcon(test);
                panel.add(labelGrid[r][c]);
            }
        }
        panel.revalidate();
    }

}

以下是通常打印的内容:

Running Code

似乎该程序只是放弃显示图像。但是请注意,每次显示的图像数量都会改变!有时可能只显示五张图像,而有时只显示22张。

当我尝试使用较小的地图时:

final int[][] MAP =
                {
                        {1, 1, 1},
                        {1, 1, 1},
                        {1, 1, 1}
                };

整个3x3图像网格大约出现一半的时间,而另一半只显示一两个图像。

可以采取什么解决方案来解决此问题?

计算机规格:

Windows 10

i8-8700

1080 ti

16GB内存

1 个答案:

答案 0 :(得分:1)

您的基本问题是误会之一...欢迎来到我的世界

使用panel.setLayout(null);意味着您对布局负全部责任,这在您知道自己在做什么的时候就可以了。

通过在建立UI之前调用setVisible并使用revalidate(用于运行布局遍历,并为麻烦做准备)来解决这个问题。

您应该使用revalidate而不是repaint来触发新的绘画过程(请注意,在正常情况下,在更新UI时应同时使用两者,但是由于'不再使用布局管理器,您不需要revalidate

例如,更好的解决方案是使用自定义绘画路线...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final int[][] MAP
                = {
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1}
                };
        protected static Dimension GRID_SIZE = new Dimension(20, 20);
        private Rectangle buf; // This represents your image

        private Dimension preferredSize;
        public TestPane() {
            buf = new Rectangle(0, 0, GRID_SIZE.width, GRID_SIZE.height);

            int max = 0;
            for (int row = 0; row < MAP.length; row++) {
                max = Math.max(max, MAP[row].length);
            }
            preferredSize = new Dimension(GRID_SIZE.width * MAP.length, GRID_SIZE.height * max);
        }

        @Override
        public Dimension getPreferredSize() {
            return preferredSize;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (int row = 0; row < MAP.length; row++) {
                for (int col = 0; col < MAP[row].length; col++) {
                    int x = GRID_SIZE.width * row;
                    int y = GRID_SIZE.height * col;
                    Graphics2D translated = (Graphics2D) g2d.create();
                    translated.translate(x, y);
                    translated.draw(buf);
                    translated.dispose();
                }
            }
            g2d.dispose();
        }

    }
}

GridLayout

另一种选择是使用GridLayout

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final int[][] MAP
                = {
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1}
                };
        protected static Dimension GRID_SIZE = new Dimension(20, 20);
        private BufferedImage buf; // This represents your image

        public TestPane() {
            int max = 0;
            for (int row = 0; row < MAP.length; row++) {
                max = Math.max(max, MAP[row].length);
            }

            setLayout(new GridLayout(MAP.length, max));

            buf = makeBuffer();
            for (int row = 0; row < MAP.length; row++) {
                for (int col = 0; col < MAP[row].length; col++) {
                    add(new JLabel(new ImageIcon(buf)));
                }
            }
        }

        protected BufferedImage makeBuffer() {
            BufferedImage img = new BufferedImage(GRID_SIZE.width, GRID_SIZE.height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = img.createGraphics();
            g2d.setColor(Color.DARK_GRAY);
            g2d.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
            g2d.dispose();
            return img;
        }

    }
}

但是这会调整单元格的大小,您可能不希望在其中使用...

GridBagLayout

这将更好地尊重组件的首选大小,并且根据当前配置的方式,当窗口大小更改时,将不会调整组件的大小

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final int[][] MAP
                = {
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 1, 1, 1}
                };
        protected static Dimension GRID_SIZE = new Dimension(20, 20);
        private BufferedImage buf; // This represents your image

        public TestPane() {
            int max = 0;
            for (int row = 0; row < MAP.length; row++) {
                max = Math.max(max, MAP[row].length);
            }

            setLayout(new GridBagLayout());

            buf = makeBuffer();
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridy = 0;
            for (int row = 0; row < MAP.length; row++) {
                gbc.gridx = 0;
                for (int col = 0; col < MAP[row].length; col++) {
                    add(new JLabel(new ImageIcon(buf)), gbc);
                    gbc.gridx++;
                }
                gbc.gridy++;
            }
        }

        protected BufferedImage makeBuffer() {
            BufferedImage img = new BufferedImage(GRID_SIZE.width, GRID_SIZE.height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = img.createGraphics();
            g2d.setColor(Color.DARK_GRAY);
            g2d.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
            g2d.dispose();
            return img;
        }

    }
}