我一直在研究一个显示16 x 16图像网格的项目,基于用户交互,该网格在比16动态更大的基础上跟随用户(例如,基础是50 x 50) x 16显示屏。但是,我使用JLabel
组件显示这些图像,并且每次用户互动时,我都必须移动256个图像中的每一个并擦除不再位于16 x 16显示网格中的图像。这导致每次按键接近一秒钟的延迟,并且接近无功能。
[我正在尝试做的是将这些图像在地面的整个宽度上链接在一起,然后将焦点简单地移到16 x 16网格内的部分,从而使该过程不再需要使用嵌套循环显示。
是否可以动态存储和创建这些链接的图像以使用标签显示?如果还有其他方法可以显示Java中的.png文件,这些文件可以以类似的方式存储和使用?
我当前必须在每次用户交互时绘制每张图像的方法的一个示例:
User user = game.user;
int floorWidth = game.floorWidth;
int floorHeight = game.floorHeight;
int pX = user.getTile().getX();
int pY = user.getTile().getY();
int minX = Math.max(pX - GameConstants.USER_DRAW_DISTANCE, 0);
int maxX = Math.min(floorWidth, pX + GameConstants.USER_DRAW_DISTANCE);
int minY = Math.max(pY - GameConstants.USER_DRAW_DISTANCE, 0);
int maxY = Math.min(floorHeight, pY + GameConstants.USER_DRAW_DISTANCE);
for (int i = minY; i < maxY; i++)
{
for (int x = minX; x < maxX; x++)
{
Tile tile = floor.getTile(x, i);
if (tile.getHasSeen())
{
JLabel cLabel = tile.imageLabel;
cLabel.setLocation(340 + x * 32, 140 + i * 32);
cLabel.setSize(64, 64);
cLabel.setVisible(true);
panel.add(cLabel, 1);
}
}
}
原则上,您的想法应该可行。因此,您可能正在做其他错误的事情。
我已经举了一个例子,其中显示了256x256 JLabel中的16x16正方形JLabel。将鼠标移到面板上时,它会更改布局以显示一组新的16x16 JLabel。更改非常快捷,绝对不会延迟1秒。
import javax.swing.*;
import java.awt.EventQueue;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.event.*;
import java.util.*;
public class GridViewer{
int x0, y0;
int N = 256;
int display = 16;
int length = 32;
List<JLabel> showing = new ArrayList<>();
List<JLabel> available = new ArrayList<>();
JPanel panel = new JPanel(){
Dimension sz = new Dimension(length*display, length*display);
@Override
public Dimension getPreferredSize(){
return sz;
}
};
public void showGui(){
JFrame frame = new JFrame();
panel.setLayout(null);
panel.addMouseMotionListener( new MouseAdapter(){
Random r = new Random();
@Override
public void mouseMoved(MouseEvent evt){
int x = evt.getX();
int y = evt.getY();
//map to position on the image to the position on the grid.
x0 = x/2;
x0 = Math.min(x0, N-display);
y0 = y/2;
y0 = Math.min(y0, N-display);
updateLayout();
}
});
for(int i = 0; i<N*N; i++){
available.add(createItem(i));
}
updateLayout();
frame.setContentPane(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
/**
* Creates a solid color jlabel, could be used to load an image
* as an icon.
**/
JLabel createItem(int i){
JLabel l = new JLabel("");
int r = (i/256);
int g = (0)&255;
int b = (i%256);
int c = (r << 16 ) + ( g << 8 ) + b;
l.setBackground(new Color(c));
l.setOpaque(true);
l.setSize(length, length);
return l;
}
public void updateLayout(){
for(JLabel l: showing){
panel.remove(l);
}
for(int i = 0; i<display; i++){
for(int j = 0; j<display; j++){
JLabel l = available.get((i + x0) + (j+y0)*N);
panel.add(l);
l.setLocation( i*length, j*length);
showing.add(l);
}
}
}
public static void main(String[] args){
EventQueue.invokeLater( () -> new GridViewer().showGui() );
}
}
一些变化。
使用GridLayout
使用布局管理器有很多优点。特别是在使用不同的显示器,字体和平台时?添加和删除元素时,可能会使部分显示元素变得困难。
使用带有ScrollPane的大型JPanel
我们可以创建一个JPanel并向其中添加所有256x256组件,然后使用滚动窗格设置视图。这将具有将布局和视图完全分离的优势。有人想要一个更大的窗口,您不必更改布局,视图变大,您可以看到更多的布局。对于256x256的组件,它应该表现良好,但是如果组件太多,则可能需要重新考虑。
使用JPanel并覆盖paintComponent
[这将涉及将'png'文件作为awt Image
(可能是BufferedImage
s)加载,并使用图形对象进行绘制。您将需要处理所有布局和渲染。它为您提供了呈现组件的强大功能。