每当鼠标指针位置等于JPanel的每个边框的位置时,我很难绘制缓冲图像的子图像。问题是等于SubImage的BufferedImage不会显示
这是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来包含Panel所有我得到的是一个错误
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);
}
答案 0 :(得分:1)
为了检测鼠标移动,您应该使用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();
答案 1 :(得分:0)
感谢您的时间和理解。
鼠标内移动
if (e.getPoint().getX() >= getWidth() - 4) {
isRightBorder = true; // unnecessary
scr_buffer = null;
x = x + 2;
repaint();
}