我从 2008 年开始在一台机器上开发,不幸的是目前无法升级。我真的需要优化我正在构建的这个工具的性能。
我的整个项目相当大,我目前正在创建自己的地图编辑器,以便以后为我的主要项目创建地图。它相当简单,旨在加载、保存和编辑地图拥有的“瓷砖”数组。它基本上是一个 2D 地图编辑器,根据我的需要进行定制。
当地图加载到编辑器中时,它的 Tileset(一个大的 BufferedImage)被分解为每个单独的 Tile(具有较小的 BufferedImage),加载到 GUI 的右侧成为一大堆带有图标的 JLabel。我使用了各种 Swing LayoutManager 来实现我想要的定位。
在 MapCanvas 区域内,基本上做了同样的事情。每个 Tile,无论是否为空,都有一个带有图标的 JLabel,加载到 Grid 上。我之前曾询问过使用 Swing 组件是否比使用 Java2D 来设计和绘图更有效,并且一致认为这并不重要(老实说,Swing 可能比我写的更好我)。
我相信我的问题源于我互连每个 JLabel 及其图标的方式。
我的目标是减少我必须创建的重复图标的数量,这在理论上应该减少内存使用和 CPU 使用。编辑器中的磁贴交互如下:
- 如果没有选择要“标记”的图块,则只会在 JLabel 的图标上绘制一个颜色的 alpha 合成,以表示它正在悬停,并且将在 MouseExit 时恢复
- 如果活动的图章工具上有一个图块,该图块的图像将临时替换 JLabel 的图标以表示它正在悬停,并且将在 MouseExit 时恢复
- 如果活动图章工具上有一个图块,并且单击了一个 JLabel,则该 JLabel 的图标将“永久”设置为活动图章图块,除非还原
- 如果启用 Grid Lines 选项,每个 JLabel 的图标将通过 ImageFactory 处理,以使虚线沿着顶部和左侧边缘延伸(形成网格,如图所示)如果缩放级别发生变化,每个JLabel 的preferredSize 设置为可容纳,并且必须在ImageFactory 中调整图标的大小(根据应用的网格线)
将 Map 加载到编辑器后,会创建每个 JLabel,并给出其对应的 BufferedImage(无论是否为空),然后将其放入 Map 的字段 ArrayList 中。设置了 preferredSize 以使 Layout 看起来正确,并将其添加到 MapCanvas(它只是一个 JPanel)。
我创建了各种 ArrayList 和 HashMap 对象,以便可以将 JLabel 作为 Key 传递,并返回 BufferedImage。这样,当悬停在 JLabel 上时,MouseEvent 可以将事件的源发送回侦听器,并且它可以根据接收到的 JLabel 获取正确的 BufferedImage。然后图像可以由我的 ImageFactory 类以上面列出的方式之一处理。
所以基本上当 JLabel 收到 MouseEvent 时,会发生这种情况:
- MouseEvent 将源 JLabel 发送到 ActionListener
- Listener 使用源 JLabel 作为 Key 来获取所需的 BufferedImage 块
- 然后相应地处理 BufferedImage 块(可以是颜色 Alpha 合成、应用到它的缩放因子或添加到它的网格线,或这些的组合)
有没有更好的方法来做到这一点?这对我用了 2 年的笔记本电脑没有任何明显的影响,但是当鼠标与我的旧台式机上的 JLabels 交互时,会有非常明显的延迟。
鉴于我将在两者上积极开发,我希望环境能够顺利运行,如果这意味着我必须对内存和 CPU 使用更严格,那就这样吧。
但我似乎真的想不出一个内存效率更高的系统。
ArrayLists 和 HashMaps 是问题吗?许多图像操作是问题吗?
我已经以各种方式利用了 JLabel 的“setName(String)”方法(例如,每个 JLabel 都有一个名称,其中包含它在 JLabel 的一维数组中的位置,以及它在图表上的 x 和 y 坐标,即“maptile#24:1,9”),但这需要遍历数组,我希望专门用键抓取 BufferedImages 会更有效。