0

I am creating a 6x6 grid memory game. Its requirements is to use an image in a panel as a replacement for the buttons.

enter image description here 210 x 70

The project requires to implement MouseListeners on the following conditions: The button will show first pokebell. When the mouse hovers over the pokeball, it changes into the second pokeball. When the mouse moves away from the pokeball, it reverts back to the first pokeball. When the mouse clicks the pokeball, it changes to the 3rd pokeball.

Grid MouseEvents

 public void mouseEntered(MouseEvent e) {
    for(i = 0; i < 36; i++){        
        if(e.getSource() == pkm[i]){                
                pkb[i].repaint();                       
        }
    }
}

public void mouseExited(MouseEvent e) {   
    for(i = 0; i < 36; i++){
        if(e.getSource() == pkm[i]){
                pkb[i].repaint();           
        }
    }  
}

PokeBall class

int start = 0;
int ht = 0, wt = 0;
URL url;
BufferedImage img, sp1;

public PokeBall(String imgLink, int w, int h, int x){
wt = w;
ht = h;
start = x;
url = this.getClass().getResource(imgLink);     
    try{   
        img = ImageIO.read(url);
    }
    catch(Exception e){         
    }
}


public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;

    sp1 = img.getSubimage(start, 0, wt, ht);  
    g2d.drawImage(sp1,20,10,null);

    if(start == 70) {
        start = 0;
    } 
    else {
        start += 70;
    }           
} 

My thought was that the change of sprite will be invoked on the corresponding mouse event, but instead I got the whole pokeball to animate in an infinite loop even when the mouse didn't invoke any event.

I need some ideas or suggestions on how to stop it from looping by itself and to actually call the designated pokeball.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Rapharlo
  • 89
  • 6
  • *"The project **requires** to implement **MouseListeners** on the following conditions:"* Wow! Tough requirement, given a `JToggleButton` could give that ability in just 3 lines of code. See this [demo](http://stackoverflow.com/a/7360696/418556) for an example. – Andrew Thompson Sep 24 '13 at 07:38
  • Yes. Sadly that's the requirement of our professor to use a panel instead of JButton or JToggleButton. – Rapharlo Sep 24 '13 at 07:42
  • BTW - how do the following two things come into it? [tag:animation] & [tag:gridlayout] – Andrew Thompson Sep 24 '13 at 07:44
  • Also, is custom painting compulsory, or might you use a `JLabel` to display the appropriate image? – Andrew Thompson Sep 24 '13 at 07:47

2 Answers2

0

Basically, the responsibility for painting the balls is the PokeBall class, it needs to know when the state has changed, so it makes sense to apply an MouseListener and MouseMotionListener to it. Then you don't need to care about trying to update grid locations and other fun stuff.

On your GridPane, I would then attach another MouseListener so you can detect when a ball is clicked and take appropriate action there...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MyPokeBalls {

    public static void main(String[] args) {
        new MyPokeBalls();
    }

    public MyPokeBalls() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new PokeBall());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class PokeBall extends JPanel {

        private BufferedImage balls;
        private int ballWidth = 70;
        private int ballHeight = 70;
        private int ballOffset = 0;

        public PokeBall() {
            try {
                balls = ImageIO.read(new File("PokeBalls.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            MouseAdapter ma = new MouseAdapter() {

                private boolean isIn = false;

                @Override
                public void mouseEntered(MouseEvent e) {
                    ballOffset = 1;
                    isIn = true;
                    repaint();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    ballOffset = 0;
                    isIn = true;
                    repaint();
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    ballOffset = 2;
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    if (isIn) {
                        ballOffset = 1;
                    } else {
                        ballOffset = 2;
                    }
                    repaint();
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(ballWidth, ballHeight);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (balls != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                BufferedImage ball = balls.getSubimage(ballWidth * ballOffset, 0, ballWidth, ballHeight);
                int x = (getWidth() - ball.getWidth()) / 2;
                int y = (getHeight() - ball.getHeight()) / 2;
                g2d.drawImage(ball, x, y, this);
                g2d.dispose();
            }
        }
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0
AbstractButton b=new JToggleButton(firstIcon);
b.setContentAreaFilled(false);
b.setFocusable(false);
b.setBorder(BorderFactory.createEmptyBorder());
b.setRolloverEnabled(true);
b.setRolloverIcon(secondIcon);
b.setSelectedIcon(thirdIcon);

Why reinventing the wheel?

Creating a grid of such buttons is quite simple…

Holger
  • 285,553
  • 42
  • 434
  • 765