-1

Im having difficulty drawing a Sub Image of a Buffered Image everytime the Mouse Pointer Location equals that of the each border of the JPanel. The problem is that the BufferedImage that is equals the SubImage wont display

Here is the JPanel the initialization might not be correct Im still learning the components of Java and 2D graphics.

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(); }


             }
        }); 

    }


}

In the main I init a JFrame to contain the Panel all im getting is a error

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 Answers2

1

In order to detect mouse movement you should use a MosuseMotionListener, while technically MouseAdapter implements this, you need to register it with the JPanel correctly

Instead of using addMouseListener, you'll want to use addMouseMotionListener instead

I'd also be worried about the use of SRC_W and SRC_H, as you can't guarantee the size of the panel. Instead, you should be using getWidth and getHeight, which will tell you the actual size of the component

You can improve the chances of obtaining the size you want by overriding the getPreferredSize and return the size you would like. You'd then use pack on the frame to wrap the frame about it

f.getContentPane().add(f); is adding the frame to itself, it should probably be more like f.getContentPane().add(m);

f.setLayout(null); will prevent any of the child components from been sized and positioned and is best avoid, just get rid of it.

Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

This scr_buffer = map_buffer.getSubimage(x, y, SCR_W, SCR_H); is also a little dangerous, as it could be asking for more of the image then is available, you should be testing to see if x + SCR_W < image width (and same goes for the height)

I don't know if this deliberate or not, but you never reset the "border" flags, so once set, they will always be 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;

You may also want to have a "space" around the edge, which when the mouse enters it, it will set the border flags, for example...

                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;
                }

Your logic for the vertical movement is wrong, when the mouse is within the bottom border, it should add to the y position and subtract when it's within the top border...

                if (isBottomBorder) {
                        y += 2;
                }
                if (isTopBorder) {
                        y -= 2;
                }

You need to perform some range checking after you've modified the x/y positions to make sure you're not request for a portion of the image which is not available...

                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();
                }

There is a logic error within the initScreen method, src_buffer is never set to null, meaning that once it has a "sub image", it never tries to obtain a new one (also, you shouldn't be loading the map_buffer in there either).

                scr_buffer = null;
                repaint();
MadProgrammer
  • 323,026
  • 21
  • 204
  • 329
  • Exception in thread "main" java.lang.IllegalArgumentException: adding container's parent to itself at java.awt.Container.checkAddToSelf(Container.java:477) at java.awt.Container.addImpl(Container.java:1088) at java.awt.Container.add(Container.java:415) at war.War.main(War.java:75) – Олег Игоревич Dec 22 '14 at 21:26
  • I setPreferredSize and changed SCR_H and W with getHieght() I still get a error. I cant seem to figure out the problem. – Олег Игоревич Dec 22 '14 at 21:28
  • 1
    Don't call `setPreferredSize`, if you can call, so can some one else, override `getPreferredSize` – MadProgrammer Dec 22 '14 at 21:33
  • `f.getContentPane().add(f);` appears to be your problem, I think you want `f.getContentPane().add(m);` – MadProgrammer Dec 22 '14 at 21:34
  • Ok I changed the component added yet JFrame doesnt hold the size that is set to and the image is not painting. And the mouseMotionListener is not being called the System..println is not printing. – Олег Игоревич Dec 22 '14 at 21:38
  • I change the NULL Layout to new BorderLayout now the image is shown yet when I move the mouse it not changing the JPanel Image upon the incremention of x y from sub image. – Олег Игоревич Dec 22 '14 at 21:49
  • This could be a good opportunity to develop some debugging skills. Put some `System.out.println` statements in your code to print the values of your variables and help you track the follow of your code, or even better, make use of the debugger itself... – MadProgrammer Dec 22 '14 at 21:53
  • I thank you for you time and understanding.. I now realize that the image is not repainted itself cause of READ ONLY MEMORY that is occurring during the Initialization of the bufferedImage. So evertime I need to change it I have erase the buffer containing the memory for the image and replace it with a new subImage. Otherwise I keep calling repaint it just going to paint on top of each and the Coordirants change yet the Image stays the same. – Олег Игоревич Dec 23 '14 at 12:07
  • Actually, it has to do with the fact that you never invalid `scr_buffer`, which means the `if (src == null)` will only be true the first time that the component is painted.... – MadProgrammer Dec 23 '14 at 12:19
  • Called it once buffer no longer null. JMP over statement cause buffer = some thing already. Thats why calling scr_buffer = null with repaint will sense the if statement to be true. How would i repaint the Image with just the mouse hovering with in a certain location. Cause XY increments only when it sense the mouse moving. – Олег Игоревич Dec 23 '14 at 12:32
  • Use a Swing Timer, check the boolean flags and update the position and repaint as required. Use the MouseMotionListener to update the state of the boolean flags only – MadProgrammer Dec 23 '14 at 18:58
  • That idea is great for a NPC to automate an algorithmic sequence of when the AI should shoot. What i want to work on is creating a selection rectangle to select jlabels and than secound click will be there location. I really like the command and conquer games. Reverse engineering is where I get most of my ideas most say reinventing the wheel is a horrible idea, yet that a really ignorant thing to say cause not many people want to understand it engineering. If it works why fix it. Well to make it better. Improvement and efficiency. – Олег Игоревич Dec 23 '14 at 22:03
  • Troubling thought is how will I write them in memory according to the XY correlating to the the screen. I dont think the computer thinks in negative XY. – Олег Игоревич Dec 23 '14 at 22:04
0

Thank you for you time and understanding.

Inside mouse moved

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

                }