斯卡拉的挥杆表现取决于赛事?

时间:2016-02-16 15:12:20

标签: performance swing scala events

我最近发现,我的scala swing应用程序表现得非常奇怪。 以下测试应用程序绘制一条在屏幕上移动的线。 当我第一次运行程序时,我感到震惊的是看起来有多么迟钝,因为线路至少没有顺畅地移动。 但是,一旦swing似乎识别出由例如鼠标悬停或按下的键触发的事件,一切似乎都按预期顺利运行。然而,只要鼠标离开摆动窗口,或者没有按下更多按键,摆动就会再次延迟。我不是在慢速机器上工作,因为我没有类似的python问题,所以我仍然认为scala.swing库对我来说似乎非常糟糕。 有没有我在这里看不到的重大错误?我不正确地使用scala.swing吗?是什么让scala.swing变得如此滞后,但只有在用户没有触发事件时才会出现这种情况?

这是我创建的非常小的测试应用程序。请复制并亲自试用。

object PerformanceTest {

  def main(args:Array[String]): Unit ={
    var i =0
    val (x1, y1) = (0,0)
    val (x2, y2) = (400,300)

    val frame = new MainFrame{
      title = "performance test"
      centerOnScreen()
      contents = new BorderPanel{
        layout += new Panel{
          override def paint(g:Graphics2D): Unit ={
            g.drawLine(x1+i, y1,x2-i, y2)
          }
        } -> BorderPanel.Position.Center
        listenTo()
      }
      size = new Dimension(400, 300)
      visible = true
    }


    while(true){
      frame.repaint()
      i += 1
      Thread.sleep(20)
    }
  }

}

2 个答案:

答案 0 :(得分:2)

你有没有机会在Linux上看到这个?我最近在JDK Linux中发现了一个刷新错误,听起来像是一回事。请参阅this question

所以我所做的就是致电.toolkit.sync()。这有点可怕,因为它根据我的理解同步整个窗口系统,而你实际上只想同步一个单独的组件。但我还没有找到更好的解决方法。

另请注意,您应该只刷新面板而不是框架。然后你必须填充背景矩形或声明它不透明。您也不应该在事件派发线程之外创建框架。而不是在Thread.sleep的主线程上等待,更好的方法是使用Swing计时器。通过这些更改,我得到了:

object PerformanceTest {
  import scala.swing._

  def main(args: Array[String]): Unit = Swing.onEDT /* ! */ {
    var i = 0
    val (x1, y1) = (0,0)
    val (x2, y2) = (400,300)

    val panel = new Panel {
      opaque = false  // !
      override def paint(g: Graphics2D): Unit =
        g.drawLine(x1 + i, y1, x2 - i, y2)
    }

    lazy val frame = new Frame {
      title = "performance test"
      contents = new BorderPanel {
        layout += panel -> BorderPanel.Position.Center
      }
      size = new Dimension(400, 300)
      centerOnScreen()

      override def closeOperation(): Unit = {
        timer.stop()
        dispose()
      }
    }

    lazy val timer: javax.swing.Timer = new javax.swing.Timer(20,
      Swing.ActionListener { _ =>
        i = (i + 1) % 400
        panel.repaint()
        panel.toolkit.sync()  // linux bug?
      }
    )

    timer.start()
    frame.open()
  }
}

PerformanceTest.main(null) // test

答案 1 :(得分:0)

先生,您是否知道您违反了Swing EDT rules