ImageIcon 的二维数组在 JPanel 中显示不一致且仅部分显示
2D array of ImageIcon's displays inconsistently and only partially in JPanel
我正在尝试使用 ImageIcons、JLabel 和 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();
}
}
这里是关于通常打印的内容:
看来程序只是放弃了显示图像。但是,请注意每次显示的图像数量都会发生变化!有时可能只出现 5 张图像,有时可能出现 22 张。
当我尝试使用较小的地图时,例如:,
final int[][] MAP =
{
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
整个 3x3 图像网格将在大约一半的时间内显示,另一半只显示一两个图像。
可以采取什么变通办法来解决这个问题?
计算机规格:
Windows10
i8-8700
1080 钛
16GB 内存
你的基本问题是误解之一......欢迎来到我的世界
使用 panel.setLayout(null);
意味着您对布局负全部责任,这很好,当您知道自己在做什么时。
在建立 UI 之前调用 setVisible
并使用用于 运行 布局传递的 revalidate
并自行设置遇到麻烦了。
而不是revalidate
,你应该使用repaint
,来触发一个新的paint pass(注意,在正常的事件过程中,你应该在更新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
这将更好地遵循组件的首选大小,并且根据当前配置的方式,当 window 大小更改时不会调整组件的大小
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;
}
}
}
我正在尝试使用 ImageIcons、JLabel 和 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();
}
}
这里是关于通常打印的内容:
看来程序只是放弃了显示图像。但是,请注意每次显示的图像数量都会发生变化!有时可能只出现 5 张图像,有时可能出现 22 张。
当我尝试使用较小的地图时,例如:,
final int[][] MAP =
{
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
整个 3x3 图像网格将在大约一半的时间内显示,另一半只显示一两个图像。
可以采取什么变通办法来解决这个问题?
计算机规格:
Windows10
i8-8700
1080 钛
16GB 内存
你的基本问题是误解之一......欢迎来到我的世界
使用 panel.setLayout(null);
意味着您对布局负全部责任,这很好,当您知道自己在做什么时。
在建立 UI 之前调用 setVisible
并使用用于 运行 布局传递的 revalidate
并自行设置遇到麻烦了。
而不是revalidate
,你应该使用repaint
,来触发一个新的paint pass(注意,在正常的事件过程中,你应该在更新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
这将更好地遵循组件的首选大小,并且根据当前配置的方式,当 window 大小更改时不会调整组件的大小
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;
}
}
}