每当鼠标指针位置等于JPanel的每个边框的位置时,我都难以绘制缓冲图像的子图像。问题是等于子图像的缓冲图像不会显示
这是初始化可能不正确的 JPanel 我还在学习 Java 和 2D 图形的组件。
public class Map extends JPanel implements MouseListener, MouseMotionListener {
private final int SCR_W = 800;
private final int SCR_H = 600;
private int x;
private int y;
private int dx;
private int dy;
String dir = "C:\imgs\war\";
private BufferedImage map_buffer;
public BufferedImage scr_buffer;
public void initScreen(int x, int y, int stage){
if(stage == 0){
try{ map_buffer = ImageIO.read(new File(dir + "map" + stage + ".jpg" ));
}catch(Exception error) { System.out.println("Error: cannot read tileset image.");
}
}
scr_buffer = map_buffer.getSubimage(x, y, SCR_W, SCR_H);
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(scr_buffer == null)
initScreen(x, y, 0);
g.drawImage(scr_buffer, 0, 0, this);
}
boolean isLeftBorder = false;
boolean isRightBorder = false;
boolean isTopBorder = false;
boolean isBottomBorder = false;
public Map(){
addMouseListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
/**
* Check location of mouse pointer if(specified_edge)move(scr_buffer)
*
*/
System.out.println("MouseMove: " + e.getPoint().getX() + " , " + e.getPoint().getY());
if(e.getPoint().getX() == SCR_W)isRightBorder = true;
if(e.getPoint().getY() == SCR_H)isBottomBorder = true;
if(e.getPoint().getX() == 0 && e.getPoint().getY() == SCR_H)isLeftBorder = true;
if(e.getPoint().getY() == 0 && e.getPoint().getX() == SCR_W)isTopBorder = true;
if(e.getPoint().getX() != 0 && e.getPoint().getX() != SCR_W
&& e.getPoint().getY() != 0 && e.getPoint().getY() != SCR_H){
isLeftBorder = false;
isRightBorder = false;
isTopBorder = false;
isBottomBorder = false;
}
if(isRightBorder){ x += 2; repaint(); }
if(isBottomBorder){ y -= 2; repaint(); }
if(isLeftBorder){ x -= 2; repaint();}
if(isTopBorder){ y += 2; repaint(); }
}
});
}
}
总的来说,我初始化一个 JFrame 来包含面板,所有 im 得到的都是一个错误
public static void main(String[] args) {
JFrame f = new JFrame("War");
f.setSize(800, 600);
f.setLayout(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Map m = new Map();
f.getContentPane().add(f);
f.setVisible(true);
}
为了检测鼠标移动,您应该使用 MosuseMotionListener
,虽然从技术上MouseAdapter
实现这一点,但您需要将其正确注册到JPanel
而不是使用 addMouseListener
,您需要改用addMouseMotionListener
我也会担心使用SRC_W
和SRC_H
,因为您无法保证面板的大小。相反,您应该使用 getWidth
和 getHeight
,这将告诉您组件的实际大小
您可以通过覆盖getPreferredSize
并返回所需的大小来提高获得所需大小的机会。 然后,您将在框架上使用pack
将框架包裹在它周围
f.getContentPane().add(f);
将框架添加到自身,它可能更像f.getContentPane().add(m);
f.setLayout(null);
将阻止任何子组件的大小和位置,最好避免,只需将其删除即可。
避免使用null
布局,像素完美布局是现代 UI 设计中的错觉。 影响组件单个尺寸的因素太多了,您都无法控制这些因素。Swing旨在以布局管理器为核心,丢弃这些将导致无休止的问题和问题,您将花费越来越多的时间试图纠正
这个scr_buffer = map_buffer.getSubimage(x, y, SCR_W, SCR_H);
也有点危险,因为它可能会要求更多的图像然后可用,你应该测试一下x + SCR_W
<图像宽度(高度也是如此(>
我不知道这是不是故意的,但你永远不会重置"边界"标志,所以一旦设置,它们将永远true
......
addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
/**
* Check location of mouse pointer if(specified_edge)move(scr_buffer)
*
*/
isRightBorder = false;
isBottomBorder = false;
isTopBorder = false;
isLeftBorder = false;
您可能还希望在边缘周围有一个"空格",当鼠标进入它时,它将设置边框标志,例如......
if (e.getPoint().getX() >= getWidth() - 4) {
isRightBorder = true;
}
if (e.getPoint().getY() >= getHeight() - 4) {
isBottomBorder = true;
}
if (e.getPoint().getX() <= 4) {
isLeftBorder = true;
}
if (e.getPoint().getY() <= 4) {
isTopBorder = true;
}
你垂直移动的逻辑是错误的,当鼠标在下边框内时,它应该加到y
位置,当它在上边框内时减去......
if (isBottomBorder) {
y += 2;
}
if (isTopBorder) {
y -= 2;
}
修改 x/y 位置后,您需要执行一些范围检查,以确保您没有请求图像中不可用的部分......
if (x < 0) {
x = 0;
} else if (x + getWidth() > map_buffer.getWidth()) {
x = map_buffer.getWidth() - getWidth();
}
if (y < 0) {
y = 0;
} else if (y + getHeight() > map_buffer.getHeight()) {
y = map_buffer.getHeight() - getHeight();
}
initScreen
方法中存在逻辑错误,src_buffer
永远不会设置为 null
,这意味着一旦它有一个"子图像",它永远不会尝试获取一个新的(此外,你也不应该在那里加载map_buffer
(。
scr_buffer = null;
repaint();
感谢您的时间和理解。
内部鼠标移动
if (e.getPoint().getX() >= getWidth() - 4) {
isRightBorder = true; // unnecessary
scr_buffer = null;
x = x + 2;
repaint();
}