显示缓冲图像使用鼠标侦听时出错



每当鼠标指针位置等于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_WSRC_H,因为您无法保证面板的大小。相反,您应该使用 getWidthgetHeight ,这将告诉您组件的实际大小

您可以通过覆盖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();
                }

最新更新