Java ImageIcons和actioin监听器

我正在创建一个简单的游戏,其中一个人点击图像,分数增加一。 看起来很简单吧? 这是捕获 – 图像将部分隐藏在其他图像后面!

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

我的第一个想法是简单地获取imageIcon的坐标隐藏,向它们添加height()和width(),并创建一个只能在指定区域中工作的鼠标监听器。 但是,这会给我一个矩形供用户点击,这会破坏隐藏对象的目的(有人可以点击前景后面图形的刚性边界)。

您对如何使鼠标动作侦听器仅在imageIcon的VISIBLE像素上有效有任何建议吗? 是的,我理解动作监听器只能应用于组件(例如按钮),但“按钮”不能完成我想要的项目。

例1

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

在此处输入图像描述

 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方法渲染图像。 它检查鼠标点处图像的像素alpha,以确定鼠标事件是否应该通过。

我使用255的alpha值有点严格,但你可以根据你的需要稍微软化一下(例如225之类的东西)……

我已经对图层进行了硬编码,以便树总是位于松鼠上方,但是按照您希望它们出现的顺序将所有图像添加到List并不困难,并且简单地沿着列表向下运行直到您获得命中。

在此处输入图像描述

 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 = px - bounds.x; int y = py - 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; } } }