【问题标题】:The image is Frozen despite calling for methods to update it尽管需要方法来更新图像,但图像仍被冻结
【发布时间】:2019-12-14 05:37:47
【问题描述】:

我正在尝试编写代码以使用 AWT 和 scala 在窗口中显示黑色圆圈。我成功地在我想要的位置绘制了圆圈,但图像被冻结了。

我在扩展 Frame 的 Display 类的 run() 方法中使用了一个简单的游戏循环:

final class Display(
    val canvas: Canvas, 
    val updater : Updater
) extends Frame  with Runnable {

  this.add(canvas)

  override def run() ={

    setSize(canvas.size())
    setVisible(true)

    var updateTime = System.currentTimeMillis()
    while(true) {
      val frameStart = System.currentTimeMillis()
      val frameEnd = frameStart + MILLIS_PER_FRAME
      repaint()
      canvas.paint(getGraphics())

      while(updateTime < System.currentTimeMillis()) {
        updater.update(MILLIS_PER_UPDATE, keyboard)
        updateTime += MILLIS_PER_UPDATE
      }

      while(System.currentTimeMillis() < frameEnd) Thread.sleep(1)
    }

    setVisible(false)
  }

我打过电话

repaint()
canvas.paint(getGraphics())

认为它会根据canvas的paint()方法再次调用在Frame上绘制图像。但显然这不是它的工作原理......

我相信我的画布的 paint(g : Graphics) 方法工作正常,并且我通过 println() 调试验证了圆圈应该在移动。

请提供任何可以帮助您回答的代码,并感谢您的回答。

【问题讨论】:

    标签: scala awt


    【解决方案1】:

    repaint() 计划组件重新绘制,但此操作尚未执行,必须在 UI 线程上执行。

    基本上每个 UI 应用程序都有一个单独的专用线程,用于计算应该如何重绘,然后重绘它们。

    您的run 操作由该线程调用,因此该线程也正在执行while(true)。意思是,它永远不会离开run,也永远不会到达负责重新绘制的代码。

    解决方案是根本不计算 UI 组件内部的任何逻辑:

    • 为计算、IO 操作等保留一个单独的线程(或线程池)
    • 当您在 UI 上执行一些更新模型、计算某事等的操作时,将其分派到单独的线程,
    • 一旦这个线程完成,它应该调用 UI 组件,以便它只执行此特定 UI 更改所需的逻辑

    您犯的是一个常见错误,您可以阅读更多有关搜索“为什么不在 UI 线程上阻塞”、“为什么单独的 UI 线程”等短语的信息。它负责诸如 UI 无响应之类的问题(您单击某些东西,然后一切都冻结了片刻),在while(true)这样的情况下,它会无限期地阻止UI。恐怕在 JVM 引入其他一些具有延续的本机方式之前,使用多线程是唯一推荐的方式。

    【讨论】:

    • 好的,谢谢!现在他们正在搬家。他们在闪烁。但我认为这个问题已经在另一篇文章中解决了。
    • 只是猜测,但我认为闪烁可能是由于重新绘制太快和/或在绘图期间没有“双缓冲”,但是,是的,这是另一个话题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2014-06-06
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多