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

Java 如何使用鼠标事件切换图像?,java,image,swing,paintcomponent,mouselistener,Java,Image,Swing,Paintcomponent,Mouselistener,我正在处理一个任务,当用户点击图像时,它会改变,一旦它通过timer类再次移动,图像就会切换回原始图像。到现在为止,我可以单击图像来更改它,但当再次移动时,它不会再更改。它移动后有没有办法换回来 这是我的密码 主要内容: 专家组: import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import

我正在处理一个任务,当用户点击图像时,它会改变,一旦它通过timer类再次移动,图像就会切换回原始图像。到现在为止,我可以单击图像来更改它,但当再次移动时,它不会再更改。它移动后有没有办法换回来

这是我的密码

主要内容:

专家组:

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

}
}
import java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.util.Random;
导入javax.swing.ImageIcon;
导入javax.swing.JPanel;
导入javax.swing.Timer;
公共类生物扩展JPanel
{
专用静态最终整数延迟=900;
专用随机生成器=新随机();
私有图像图标图像,图像1;
私人定时器;
私有整数x,y;
私有int catchCount=0;
公共生物()
{  
image=新的图像图标(“pikachu.png”);
image1=新的ImageIcon(“pokeball.png”);
定时器=新定时器(延迟,new MoveListener());
x=发电机。nextInt(1900);
y=发电机下一个(1000);
addMouseListener(新的MouseClickedListener());
挫折背景(颜色:绿色);
设置首选尺寸(新尺寸(19001000));
timer.start();
}  
//绘制图像。
公共组件(图形页)
{  
super.paintComponent(第页);
image.paintIcon(此,第页,x,y);
第页。拉丝(“捕获的皮卡丘斯:”+catchCount,10,35);
setFont(新字体(“Arial”,字体粗体,35));
}
//移动图像的方法。
公开作废动议()
{
timer.start();
x=发电机。nextInt(1900);
y=发电机下一个(1000);
if(timer.isRunning())
{
x=发电机。nextInt(1900);
y=发电机下一个(1000);
}
重新油漆();
}
//获取捕获次数的方法。
public int getCatchCount()
{  
返回捕获计数;
}  
//使图像移动
私有类MoveListener实现ActionListener
{
已执行的公共无效操作(操作事件)
{
move();
重新油漆();
} 
} 
//当用户单击图像时记录。
私有类MouseClickedListener扩展了MouseAdapter
{  
公共void mouseClicked(MouseEvent事件)
{  
if((event.getButton()==MouseEvent.BUTTON1)&&between(event.getX(),x,x+image.getIconWidth())&&between(event.getY(),y,y+image.getIconHeight())
{
System.out.println(“抓到一个!”);
catchCount++;
move();
图像=图像1;
}
}
}
私有静态布尔值介于(整数x、整数下限、整数上限)之间
{

return(x>=lower)&&(x我希望我能理解您试图实现的目标。首先,您需要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 );
    ...
}
不要忘记将图像更改为imageToDraw in paint():

从onclick事件中删除move();并在单击操作中将图像更改为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;

            }

   }

编辑:move();已从onclick事件中删除。您需要一种方法来绘制任一图像。现在您只需将
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);
}
现在,您要做的第一件事不是重新分配
图像
,而是将标志设置为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结束时将其排队,并且在先前排队的任务完成后将对其进行更改。因此,在鼠标事件退出后,以及在您刚刚在
移动中请求的重新绘制之后

“我把所有这些都贴出来,以防有人想就其他事情或一般性问题提供建议。”

  • 您正在调用
    timer。在
    move
    中启动
    ,这似乎不是必需的。默认情况下,计时器会重复
  • move
    生成
    x
    y
    两次。由于在构造函数中调用
    timer.start
    timer.isRunning
    将始终为真
  • MoveListener
    在调用
    move
    之后调用
    repaint
    ,但是
    move
    也调用
    repaint
“如果人们愿意,也可以自己测试。”

我们无法运行它,因为我们没有您的图像。如果您想发布它,我们可以运行它,请更改代码,使其在没有图像的情况下工作。否则,我们必须自行更改。下面是一个返回空白图像图标的静态方法:

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

而不是发布你所有的代码(以及你声称有效的大量代码),为什么不发布你试图做你解释过的事情的代码呢?你说它不会变回来是什么意思?你是说取消移动吗?既然我是一个noob,我还是会发布所有的代码,以防有人想就其他事情提供建议。如果人们愿意的话,也可以自己测试。这是一个移动的pika随机移动的pikachu,当用户单击它时,会显示pokeball的图像,但只有在它再次移动之前才会显示。单击它时,还会记录它被捕获的次数。当它再次移动时,pikachu将显示,直到再次单击为止。那么,你有什么问题吗?非常感谢Johnny!我这样做并采取了移动();在点击事件之外,它工作得很好。现在,pickachu在一个pokeball中被捕获(它现在显示这个以及输出amou)
System.out.println("CAUGHT ONE!");
catchCount++;
justCaptured = true;
move();

SwingUtilities.invokeLater(new Runnable() {
    @Override public void run() {
        justCaptured = false;
    }
});
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);
}