【问题标题】:Heap overflow implementing Undo in Swing App在 Swing App 中实现 Undo 的堆溢出
【发布时间】:2025-12-09 17:05:03
【问题描述】:

我正在用 java swing 开发一个涂鸦类型的应用程序。它处于初级阶段,并在此处显示。

我已经实现了撤消最后绘制的笔划的撤消功能。撤消功能可以达到最大定义的撤消级别。

撤消功能通过在Image array 中的每个笔划之后复制绘图画布的内容来工作。 这个数组就像一个First-In-Last-Out Stack。单击撤消时,堆栈为poped 并将获得的图像绘制在屏幕上。

现在我面临的问题是,当前执行撤消的方法占用了太多内存。撤消级别为 20 时,几乎 70-80 MB 的内存被用完,而级别为 30 时,会发生堆溢出。

有没有更好的方法来实现撤销功能?谢谢。

编辑:我发现了一些有用的信息here,可能会有所帮助。

【问题讨论】:

  • 听起来您在每次笔画后都保存了整个图像。它是否正确?在我看来,最好保存每个单独的笔画,然后根据所有单独的笔画绘制图像。
  • @adchilds 是的,我会在每次笔画后保存整个图像。
  • @adchilds 表示您建议只保存以前的更改,就像补丁一样
  • 不是每次都保存整个画布(图像会占用大量内存!),而是将每个单独的笔画添加到您的堆栈中,然后单独绘制每个笔画,这应该会自己创建整个图像。跨度>
  • @david 序列化绝对是一种选择,但我担心运行时性能

标签: java swing undo


【解决方案1】:

您需要以不同的方式表示绘图中的步骤。在您当前使用的方法中,您每次都将 Canvas 重新保存为未压缩的图片 - 这是内存贪婪的。

尝试重构您的代码,以便只有在画布上绘制的笔画才会保存到堆栈中。这会在渲染图片时增加一点开销(每次发生更改时都需要重新绘制整个画布),但 Java 旨在处理这个问题。

仅保存形状后,内存需求应该会显着降低。使用Shape 类来表示画布上的笔触。

【讨论】:

  • 如果我保存形状,这意味着绘图的矢量样式
  • @2012-EndoftheWorld 如果这是位图绘制,你仍然可以做到这一点。您可以跟踪笔画的参数(路径、不透明度、大小等),而不是使用 Shape 类进行矢量绘图,然后将其保存。使用 undo 重新绘制画布时,您可以通过跟踪记忆中的笔画来重新创建整个画面。
最近更新 更多