如何使用鼠标事件切换图像?

时间:2013-12-05 00:21:13

标签: java image swing paintcomponent mouselistener

我正在处理一个图像移动的任务,当用户点击图像时它会改变,一旦它再次通过计时器类移动,图像就会恢复到原始状态。截至目前,我可以点击图片进行更改,但是当它再次移动时它不会改变。移动后有没有办法改变回来?

这是我的代码

主:

import java.awt.*;
import javax.swing.*;

public class Catch_The_Creature 
{
public static void main(String[] args) 
{
    JFrame frame = new JFrame("Catch the Creature");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JOptionPane.showMessageDialog(frame, "Catch Pikachu!");
    frame.getContentPane().add(new Creature());
    frame.pack();
    frame.setVisible(true);
}
}

面板:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Creature extends JPanel 
{
private static final int DELAY=900;
private Random generator = new Random();  
private ImageIcon image, image1;
private Timer timer;
private int x, y;  
private int catchCount=0; 

public Creature()  
{  
    image = new ImageIcon ("pikachu.png");
    image1 = new ImageIcon ("pokeball.png");
    timer =  new Timer(DELAY, new MoveListener());
    x = generator.nextInt( 1900 );
    y = generator.nextInt(1000);
    addMouseListener (new MouseClickedListener());  
    setBackground (Color.green);  
    setPreferredSize(new Dimension(1900,1000));
    timer.start();
}  
//Draws the image.
public void paintComponent(Graphics page)
{  
    super.paintComponent(page);  
    image.paintIcon (this, page, x, y); 
    page.drawString("Pikachus Captured: " + catchCount, 10, 35);  
    setFont(new Font("Arial", Font.BOLD,35));

}
//Method for moving the image.
public void move()
{
    timer.start();
    x = generator.nextInt( 1900 );
    y = generator.nextInt(1000);
    if (timer.isRunning())
    {
        x = generator.nextInt( 1900 );
        y = generator.nextInt(1000);
    }
    repaint();
}
//Method for getting the number of times caught.
public int getCatchCount()  
{  

    return catchCount;  
}  
//Makes the image move
private class MoveListener implements ActionListener
{
    public void actionPerformed(ActionEvent event)
    {
        move();
        repaint();  

    } 
} 
//Records when the user clicks the image.
private class MouseClickedListener extends MouseAdapter  
{  
       public void mouseClicked(MouseEvent event)
       {  

           if((event.getButton() == MouseEvent.BUTTON1) && between(event.getX(), x, x + image.getIconWidth()) &&  between(event.getY(), y, y + image.getIconHeight()))
                {
                    System.out.println("CAUGHT ONE!");
                    catchCount++;
                    move();
                    image=image1;

                }

       }
 }
private static boolean between(int x, int lower, int upper)
{
    return (x >= lower) && (x <= upper);

}
}

2 个答案:

答案 0 :(得分:1)

我希望我明白你想要实现的目标。首先你需要3张图片:

private ImageIcon imageToDraw, image1, image2;

生物现在看起来像这样:

public Creature()  
{  
    image1 = new ImageIcon ("pikachu.png");
    image2 = new ImageIcon ("pokeball.png");
    imageToDraw = image1;
    ...
}

在move()中你应该将图像设置为image1:

public void move()
{
    imageToDraw = image1;
    timer.start();
    x = generator.nextInt( 1900 );
    ...
}

别忘了在paint()中将图像更改为imageToDraw:

public void paintComponent(Graphics page)
{  
    super.paintComponent(page);  
    imageToDraw.paintIcon (this, page, x, y);
    ...
}

删除move();来自onclick-event并在click-action中将image更改为imageToDrwa:

public void mouseClicked(MouseEvent event)
   {  

       if((event.getButton() == MouseEvent.BUTTON1) && between(event.getX(), x, x + image.getIconWidth()) &&  between(event.getY(), y, y + image.getIconHeight()))
            {
                System.out.println("CAUGHT ONE!");
                catchCount++;
                //move(); should be removed
                imageToDraw=image1;

            }

   }

编辑:移动();从onclick-event

中删除

答案 1 :(得分:1)

您需要一种方法来绘制图像。现在,您只需将image分配给image1,当您这样做时,来自"pikachu.png"的图片就会消失。

如果没有重组太多,你可以为一个人画一个标志:

/* as a field */
private boolean justCaptured;

现在你必须稍微改变你的绘画逻辑:

if (justCaptured) {
    image1.paintIcon (this, page, x, y);
} else {
    image.paintIcon (this, page, x, y);
}

现在你要做的第一件事就是不要重新分配image,而是将标志设置为true:

System.out.println("CAUGHT ONE!");
catchCount++;
justCaptured = true;
move();

您需要做的最后一件事是将标志设置为false,以便进行下一次抽奖。有一些不同的方法可以解决这个问题,但我认为最简单的方法是在不重构一些事情的情况下将其排队等待以后:

System.out.println("CAUGHT ONE!");
catchCount++;
justCaptured = true;
move();

SwingUtilities.invokeLater(new Runnable() {
    @Override public void run() {
        justCaptured = false;
    }
});

使用invokeLater会将其排入EventQueue的末尾,并在完成先前排队的任务后更改它。因此,在鼠标事件退出之后,然后在重新绘制后,您刚刚在move中请求。

“我发布了所有内容,以防有人想就其他一般事情提出建议。”

  • 您在timer.start中呼叫move,但这似乎没有必要。定时器默认重复。
  • move生成xy两次。由于您在构造函数中调用timer.starttimer.isRunning将始终为真。
  • MoveListener在致电repaint后致电move,但move也致电repaint

“如果他们愿意的话,人们也可以自己测试。”

我们无法运行它,因为我们没有你的图像。如果你想发布它,我们就可以运行它来改变代码,这样它就可以在没有它们的情况下运行。否则我们必须以某种方式改变它自己。这是一个返回空白ImageIcon的静态方法:

public static ImageIcon createBlankIcon(int w, int h, Color color) {
    BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

    Graphics2D g2d = img.createGraphics();

    g2d.setColor(color);
    g2d.fillRect(0, 0, w, h);
    g2d.dispose();

    return new ImageIcon(img);
}

您可以用类似内容替换内容,例如:image = getBlankIcon(50, 50, Color.RED);