我正在尝试使用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();
}
}
以下是通常打印的内容:
似乎该程序只是放弃显示图像。但是请注意,每次显示的图像数量都会改变!有时可能只显示五张图像,而有时只显示22张。
当我尝试使用较小的地图时:
final int[][] MAP =
{
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
整个3x3图像网格大约出现一半的时间,而另一半只显示一两个图像。
可以采取什么解决方案来解决此问题?
计算机规格:
Windows 10
i8-8700
1080 ti
16GB内存
答案 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;
}
}
}