使用鼠标Listening显示bufferedImage重绘的错误

时间:2014-12-22 20:32:27

标签: java jpanel bufferedimage scrollable

每当鼠标指针位置等于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);


    }

2 个答案:

答案 0 :(得分:1)

为了检测鼠标移动,您应该使用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();

答案 1 :(得分:0)

感谢您的时间和理解。

鼠标内移动

if (e.getPoint().getX() >= getWidth() - 4) {
                        isRightBorder = true; // unnecessary 
                        scr_buffer = null;
                        x = x + 2;
                        repaint();

                }