尽管调用了更新图像的方法,但图像仍然冻结

时间:2019-08-06 15:56:08

标签: scala awt

我正在尝试编写代码以显示使用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()进行了验证-调试了圆圈应该在运动。

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

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

您所做的是一个常见错误,您可以阅读更多有关搜索短语的信息,例如“为什么不阻止UI线程”,“为什么单独的UI线程”等。这是导致UI无响应(单击某些内容,然后所有内容都会冻结一会儿),在while(true)之类的情况下,它会无限期阻止用户界面。恐怕在JVM引入其他一些具有延续性的本地方法之前,唯一推荐的方法是使用多个线程。