Java ImageIcons 和 actions 侦听器

2023-12-03

我正在创建一个简单的游戏,人们点击图像,分数就会增加一分。 看起来很简单,对吧?问题是——图像将部分隐藏在其他图像后面!

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

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

您对如何使鼠标操作侦听器仅在 imageIcon 的可见像素上工作有什么建议吗?是的,我知道动作侦听器只能应用于组件(例如按钮),但“按钮”并不能满足我对该项目的要求。


实施例1

这基本上使用了一系列JLabels on a JLayeredPane。每个标签都有自己的鼠标监听器,当您将鼠标悬停在其上时,它将变成红色。但是,如果它上面有一个标签,它不会响应鼠标事件......

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

我对 alpha 值的使用有点严格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;
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java ImageIcons 和 actions 侦听器 的相关文章

随机推荐

  • 使用 Gatsbyjs 包含本地 JS 和 CSS 文件

    我对这个完全陌生gatsbyjs生态系统 同时我正在学习一些reactjs 我最近购买了一个 html 模板 并尝试将其用作 UIgatsbyjs应用 该模板有很多 css 和 js 无论是专有的还是定制的 这意味着没有插件gatsbyjs
  • 添加对 Jtree 的拖放支持

    我想为我的 JTree 应用程序添加拖放支持 我创建了一个自定义的 DefaultMutableTreeNode 子类 有一个默认的 TreeCellRenderer 我需要添加哪些内容以及在哪里添加 最简单的方法是1 调用tree set
  • UIWebView 没有释放内存

    我在尝试恢复分配给 a 的内存时遇到了一些真正的麻烦UIWebView在我的应用程序中 我本质上是创造并呈现UIWebView暂时为用户单独ViewController 然后删除所有引用并弹出ViewController从堆栈中 尽管做了所
  • 如何使用 Lambda 函数对 Alexa Skill 应用程序进行异步 API 调用?

    我想从 Lambda 函数调用 api 我的处理程序由包含两个必需插槽的意图触发 因此我事先不知道我是否会退货Dialog Delegate指令或我对 api 请求的响应 在调用意图处理程序时 我如何承诺这些返回值 这是我的处理程序 con
  • 更新过期的 iO​​S MDM 配置文件

    因此 我设置了 SCEP 服务器来生成 iOS 身份证书 该证书仅在短时间内有效 当它过期时 配置文件会显示 此配置文件已过期 请更新此配置文件以获取更新版本 并显示 更新配置文件 按钮 然而 单击此按钮只会告诉我 无法更新配置文件 请联系
  • 查找非零元素的索引并按值分组

    我用 python 编写了一段代码 它接受 numpy 矩阵作为输入 并返回按相应值分组的索引列表 即 输出 3 返回值为 3 的所有索引 然而 我缺乏编写矢量化代码的知识 不得不使用 ndenumerate 来完成 这个操作只花了大约9秒
  • this.href 与 $(this).attr('href')

    读完这篇文章后net tutsplus com tutorials javascript ajax 14 helpful jquery tricks notes and best practices 我得出的结论是使用这个 href更有效率
  • Google 文档的 Apps 脚本 findText()

    我正在将正则表达式搜索应用于谷歌文档带有一些 Markdown 代码块刻度 的文本 在我的文档上运行下面的代码将返回空结果 var codeBlockRegEx 3 s 3 RegEx to find lazily all text bet
  • 如何使用 build-number 插件在 Maven 中显示 SVN 版本

    如何使用内部版本号插件显示 svn 版本和时间戳 目前我有以下内容
  • iPhone将彩色图像转换为2位图像(黑白)

    我需要帮助将彩色图像转换为 黑白 而不是灰度 我如何使用 iPhone SDK 和 Core Graphics 来做到这一点 因为我相信这是可能的 这是可能的 我之前尝试过两条路径 转换为灰度 然后逐像素转换为黑白 问题是我在透明图像上没有
  • 我应该绑定什么数据类型作为查询参数以与 Oracle ODBC 中的 NUMBER(15) 列一起使用?

    我刚刚被SO问题中描述的问题所困扰绑定 int64 SQL BIGINT 作为查询参数会导致在 Oracle 10g ODBC 中执行期间出错 我正在使用 ODBC 2 将 C C 应用程序从 SQL Server 移植到 Oracle 对
  • 从函数返回多个值

    UPDATE 这是 WIP 功能 我现在的疑问是 如何调用该函数 如
  • 实体框架在克隆后附加异常

    在尝试了几种拥有体面机制的选项之后 该机制允许使用 ObservableCollections 并可以选择使用编辑窗口和绑定动态更新它们 而无需在对绑定控件进行更改时更新全局集合 到目前为止 最好的解决方案似乎是be 克隆实体 分离旧实体
  • 为什么我在尝试访问没有任何条款的taxonomy.php 页面时收到 404 错误(Wordpress 看不到分类页面)

    我正在尝试创建分类页面 因此我使用分类法taxonomy nowe php 创建了分类法 但我的 WP 看不到该页面 或者我弄乱了重写 URL 有人可以检查我的代码并看看我是否做错了什么 我通过保存平原来刷新永久链接 然后返回到帖子名称永久
  • 当变量未定义时跳过 Ansible 任务

    我在剧本中有以下任务 name task xyz copy src item dest tmp item with items y z when y z is defined y z未定义 因此我希望跳过该任务 相反 我收到 FAILED
  • 如何在 COCOS2d Android 中使用 CClistview?

    我正在开发一个cocos2d 游戏 在这个游戏中 我必须按级别显示分数 Level Score 1 500 2 600 3 900 我想在我的游戏中使用 cclistview 有谁知道 cclistview 以及它在 Android coc
  • Umbraco Archetype 渲染图像 (MediaPicker 2)

    我正在使用 Umbraco 中的 Archtype 构建图像滑块 当我开始这个时 我正在使用 umbraco 7 5 9 和 Umbraco MediaPicker 但同时我使用最新版本的 Umbraco 7 6 2 启动了一个新项目 该项
  • 卡号前 12 位数字应安全输入,其余 4 位数字正常

    卡号前 12 位数字应为安全输入 其余 4 位数字应为正常输入 例如我正在输入卡号 4111 1111 1111 1111 在文本字段中输入此文本时 前 12 位数字应为安全输入 后 4 位数字应为正常输入即 1111 最终卡号将类似于 X
  • 根据值更改 CSS

    我被要求对值进行小型验证 如果值大于或小于 0 我需要更改或添加 删除 td 和 i 标记的 css 我的桌子看起来像这样 table class table table hover thead tr th Year th tr thead
  • Java ImageIcons 和 actions 侦听器

    我正在创建一个简单的游戏 人们点击图像 分数就会增加一分 看起来很简单 对吧 问题是 图像将部分隐藏在其他图像后面 目前 我正在使用几个 imageIcons 来设置我的场景 例如 我的前景有一个图像 foreground png 我的背景