2D массив отображений ImageIcon непоследователен и только частично в JPanel - PullRequest
0 голосов
/ 22 февраля 2019

Я пытаюсь создать экран, полный плиток для пола 16x16, используя ImageIcons, JLabels и JPanel.Моя проблема в том, что всякий раз, когда я пытаюсь отобразить эти плитки с помощью 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

16 ГБ ОЗУ

1 Ответ

0 голосов
/ 22 февраля 2019

Ваша основная проблема заключается в недоразумении ... и добро пожаловать в мой мир Using

Использование panel.setLayout(null); означает, что вы берете на себя полную ответственность за макет, что хорошо, когда вы знаете, что делаете.

Соедините это с вызовом setVisible перед установкой пользовательского интерфейса и использованием revalidate, который используется для запуска прохода макета, и вы настраиваете себя на неприятности.

Вместо revalidate вы должны использовать repaint, чтобы инициировать новый проход рисования (обратите внимание, что при обычном ходе событий вы должны использовать оба варианта при обновлении пользовательского интерфейса, но так как вы больше не используете макетменеджер, вам не нужно 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;
        }

    }
}
...