2013-04-08 49 views
1

我正在创建一个简单的游戏,其中一个人点击图像的分数会增加1。 这似乎很简单,对吧?这就是抓拍 - 图像将部分隐藏在其他图像之后!Java ImageIcons和actioin听众

目前,我用几个imageIcons设置我的场景。例如,我的前景有一个图像“foreground.png”,我的背景是“background.png”,隐藏在两者之间的图像是“hiding.png”。

我首先想到的是简单地让ImageIcon的隐藏的坐标,高度()和宽度()添加到它们,并创建一个鼠标侦听器,将只在指定的区域工作。但是,这会给我一个矩形,让用户单击它来打破隐藏对象的目的(某人可以单击前景背景中图形的刚性边界)。

你有关于如何使只有一个ImageIcon的可见光像素鼠标动作侦听器的工作有什么建议?是的,我明白,动作侦听器只能应用于组件(如按钮),但“按钮”只是没有做我想要的这个项目。

+2

这取决于你是如何呈现的图像。如果您使用'JLabel',您可以根据组件Layout的Z-Order将一个鼠标监听器附加到'JLabel',那么您只能点击标签的可见区域(如上图所示会消耗它) – MadProgrammer 2013-04-08 04:54:55

+0

我可以在图像后面绘制JLabel(我覆盖paintComponent()以绘制前景和背景)? – JavaJew22 2013-04-08 05:00:44

+0

你关心透明度吗? – MadProgrammer 2013-04-08 05:07:40

回答

5

实施例1

这基本上使用上的JLayeredPane一系列JLabel秒。每个标签都有它自己的鼠标监听器,当你将鼠标放在它上面时,它会变成红色。但是,如果有它上面的标签,也不会响应鼠标事件...

enter image description here

import java.awt.AlphaComposite; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JLayeredPane; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class ClickMyImages { 

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

    public ClickMyImages() { 
     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 TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JLayeredPane { 

     public TestPane() { 
      try { 
       BufferedImage img1 = ImageIO.read("/Image1"); 
       BufferedImage img2 = ImageIO.read("/Image2"); 
       BufferedImage img3 = ImageIO.read("/Image3"); 
       BufferedImage img4 = ImageIO.read("/Image4"); 
       BufferedImage img5 = ImageIO.read("/Image5"); 

       JLabel label1 = new ClickableLabel(new ImageIcon(img1)); 
       JLabel label2 = new ClickableLabel(new ImageIcon(img2)); 
       JLabel label3 = new ClickableLabel(new ImageIcon(img3)); 
       JLabel label4 = new ClickableLabel(new ImageIcon(img4)); 
       JLabel label5 = new ClickableLabel(new ImageIcon(img5)); 

       Dimension masterSize = getPreferredSize(); 

       Dimension size = label1.getPreferredSize(); 
       label1.setBounds((masterSize.width - size.width)/2, (masterSize.height - size.height)/2, size.width, size.height); 
       Point masterPoint = label1.getLocation(); 
       size = label2.getPreferredSize(); 
       label2.setBounds(
         masterPoint.x - (size.width/2), 
         masterPoint.y - (size.height/2), 
         size.width, size.height); 
       size = label3.getPreferredSize(); 
       label3.setBounds(
         masterPoint.x + (size.width/2), 
         masterPoint.y - (size.height/2), 
         size.width, size.height); 
       size = label4.getPreferredSize(); 
       label4.setBounds(
         masterPoint.x - (size.width/2), 
         masterPoint.y + (size.height/2), 
         size.width, size.height); 
       size = label5.getPreferredSize(); 
       label5.setBounds(
         masterPoint.x + (size.width/2), 
         masterPoint.y + (size.height/2), 
         size.width, size.height); 

       add(label1); 
       add(label2); 
       add(label3); 
       add(label4); 
       add(label5); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

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

    // This is for demonstration purposes only! 
    public class ClickableLabel extends JLabel { 

     private boolean isIn = false; 

     public ClickableLabel(Icon image) { 
      super(image); 
      addMouseListener(new MouseAdapter() { 
       @Override 
       public void mouseEntered(MouseEvent e) { 
        isIn = true; 
        repaint(); 
       } 

       @Override 
       public void mouseExited(MouseEvent e) { 
        isIn = false; 
        repaint(); 
       } 
      }); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (isIn) { 
       Graphics2D g2d = (Graphics2D) g.create(); 
       g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); 
       g2d.setColor(Color.RED); 
       g2d.fillRect(0, 0, getWidth(), getHeight()); 
       g2d.dispose(); 
      } 
     } 
    } 
} 

实施例2

下面的例子使用的paintComponent方法来渲染器图片。它检查鼠标点处图像的像素阿尔法,以确定鼠标事件是否应该通过。

我已经有点严格使用255的α值,但你可以软化了一点根据您的需要(像225,而不是为例)...

我硬编码的使树始终位于松鼠上方,但按照您希望它们出现的顺序将所有图像添加到List并不难,并且简单地沿着列表运行直到您获得命中。

enter image description here

import java.awt.AlphaComposite; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Composite; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class ClickMyDrawnImages { 

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

    public ClickMyDrawnImages() { 
     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 TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private BufferedImage tree; 
     private BufferedImage squirrel; 
     private BufferedImage mouseOver; 

     public TestPane() { 
      try { 
       tree = ImageIO.read(new File("Tree.png")); 
       squirrel = ImageIO.read(new File("Squirrel.png")); 
      } catch (IOException exp) { 
       exp.printStackTrace(); 
      } 
      addMouseMotionListener(new MouseAdapter() { 
       @Override 
       public void mouseMoved(MouseEvent e) { 
        if (withinTree(e.getPoint())) { 
         mouseOver = tree; 
        } else if (withinSquirrel(e.getPoint())) { 
         mouseOver = squirrel; 
        } else { 
         mouseOver = null; 
        } 
        repaint(); 
       } 
      }); 
     } 

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

     protected boolean withinTree(Point p) { 
      return withinBounds(p, getTreeBounds(), tree); 
     } 

     protected boolean withinSquirrel(Point p) { 
      return !withinBounds(p, getTreeBounds(), tree) && withinBounds(p, getSquirrelBounds(), squirrel); 
     } 

     protected Rectangle getTreeBounds() { 
      int width = getWidth(); 
      int height = getHeight(); 

      int x = (width - tree.getWidth())/2; 
      int y = (height - tree.getHeight())/2; 

      return new Rectangle(x, y, tree.getWidth(), tree.getHeight()); 
     } 

     protected Rectangle getSquirrelBounds() { 
      Rectangle bounds = getTreeBounds(); 

      return new Rectangle(
        bounds.x - (squirrel.getWidth()/4), 
        (getHeight() - squirrel.getHeight())/2, 
        squirrel.getWidth(), squirrel.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int width = getWidth(); 
      int height = getHeight(); 

      int x = (width - tree.getWidth())/2; 
      int y = (height - tree.getHeight())/2; 

      g.drawImage(highlight(squirrel), x - (squirrel.getWidth()/4), (height - squirrel.getHeight())/2, this); 
      g2d.drawImage(highlight(tree), x, y, this); 

      g2d.dispose(); 
     } 

     protected BufferedImage highlight(BufferedImage img) { 
      BufferedImage highlight = img; 
      if (img.equals(mouseOver)) { 
       highlight = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2d = highlight.createGraphics(); 
       g2d.setColor(Color.RED); 
       g2d.drawImage(img, 0, 0, this); 

       g2d.setComposite(AlphaComposite.SrcAtop.derive(0.5f)); 
       g2d.fillRect(0, 0, highlight.getWidth(), highlight.getHeight()); 
       g2d.dispose(); 
      } 
      return highlight; 
     } 

     protected boolean withinBounds(Point p, Rectangle bounds, BufferedImage image) { 
      boolean withinBounds = false; 
      if (bounds.contains(p)) { 
       int x = p.x - bounds.x; 
       int y = p.y - bounds.y; 
       int pixel = image.getRGB(x, y); 
       int a = (pixel >> 24) & 0xFF; 
       // could use a little weighting, so translucent pixels can be effected 
       if (a == 255) { 
        withinBounds = true; 
       } 
      } 
      return withinBounds; 
     } 
    } 
} 
+0

非常感谢!这正是想要做的 – JavaJew22 2013-04-08 05:20:28

+0

+1,很酷的例子。 – camickr 2013-04-08 05:58:13

+0

@ JavaJew22我已经更新以包含一个自定义绘图示例。 – MadProgrammer 2013-04-08 05:59:51