简体   繁体   English

斯卡拉摇摆表演取决于事件吗?

[英]scala swing performance depends on events?

I recently discovered, that my scala swing applications behave very strangely. 我最近发现,我的scala swing应用程序的行为非常奇怪。 The following test application draws a line which moves over the screen. 以下测试应用程序绘制了一条在屏幕上移动的线。 When I ran the program the first time I was shocked on how laggy swing seems to be, since the line doesnt move smoothely in the least. 当我第一次运行程序时,我对摆动似乎很慢感到震惊,因为这条线至少没有平稳地移动。 BUT as soon as swing seems to recognize events, triggered by for example a mouse-hover or pressed keys, everything seems to run smoothly and as expected. 但是,一旦摆动似乎能够识别出事件(例如由鼠标悬停或按下的键触发),一切似乎就可以按预期运行。 However as soon as the mouse leaves the swing window,or no more keys are pressed swing is laggy again. 但是,一旦鼠标离开了摆动窗口,或者不再按下任何键,摆动就会再次变得缓慢。 I am not working on a slow machine and since I dont have similar problems with python or so I still think that the scala.swing library seems to very bad, to me. 我不是在慢速机器上工作,因为我在python上没有类似的问题,所以我仍然认为scala.swing库对我来说似乎非常糟糕。 Is there a major mistake I am not seeing here? 我在这里没有看到重大错误吗? Am I using scala.swing incorrectly? 我使用scala.swing错误吗? What is it, that makes scala.swing so laggy but only ever when there are no events triggered by the user? 这是什么使scala.swing如此缓慢,但是只有在没有用户触发事件的情况下,才如此?

Here is the very small test app I have created. 这是我创建的非常小的测试应用程序。 Please copy it and try it yourself. 请复制并自己尝试。

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)
    }
  }

}

Are you by any chance seeing this on Linux? 您是否有机会在Linux上看到此消息? I have discovered a refresh bug in the JDK Linux recently that sounds like the same thing. 我最近在JDK Linux中发现了一个刷新错误,听起来像是同一件事。 See this question . 看到这个问题

So what I did is call .toolkit.sync() . 所以我要做的就是调用.toolkit.sync() This is kind of horrible because it syncs the entire windowing system as far as I understand, while you actually just want to sync one individual component. 据我所知,这很可怕,因为它实际上同步了整个窗口系统,而您实际上只想同步一个单独的组件。 But I haven't found any better workaround yet. 但是我还没有找到更好的解决方法。

Also note that you should probably just refresh the panel and not the frame. 另请注意,您可能应该只刷新面板而不是刷新框架。 Then you'll have to fill the background rectangle or declare it non-opaque. 然后,您必须填充背景矩形或将其声明为不透明。 You should also not create the frame outside of the event dispatch thread. 您也不应在事件分发线程之外创建框架。 Instead of waiting on the main thread with Thread.sleep , a better approach is to use a Swing timer. 与其使用Thread.sleep等待主线程,不如使用一个Swing计时器来更好。 With these changes I get: 通过这些更改,我得到:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM