【问题标题】:Java: How to interrupt a program partway through execution with a mouseclickJava:如何通过单击鼠标在执行过程中中断程序
【发布时间】:2012-01-28 03:34:21
【问题描述】:

如何实现一个mouselistener(或其他方式,无关紧要)来处理程序任何部分的鼠标点击事件?最好在单击事件处理程序方法完成时返回到它离开的行。

我正在使用秋千。 “上下文”是一个不断更新的 GUI,但必须随时响应用户的鼠标点击,没有延迟。事实上,我确实有事件、使用和覆盖它们的处理程序等方面的经验,我想不是太深入,但到目前为止我所知道的已经足够了。

【问题讨论】:

  • 一些问题:Swing,您使用的是什么 GUI 库? SWT?这里的背景是什么——你具体想做什么(通常不像你所描述的那样)?您熟悉事件驱动编程的基本概念吗?
  • 我很确定你会想要使用线程。一个(或多个)用于 GUI,一个用于鼠标单击事件侦听器

标签: java swing events event-handling mouselistener


【解决方案1】:

我无法理解你的第一段,所以如果我理解正确的话,我的答案是你的第二段。 ;)

Swing 遵循单线程模型。因此,您应该从 Event Dispatch Thread (EDT) 更新 UI。该线程也负责将事件传递给您的代码,因此得名。如果您在循环中不断更新 UI,那么这将使 EDT 保持忙碌和阻塞。最终效果将是一个不响应用户事件的 UI。这是因为事件正在排队,EDT 可以挑选它们并在空闲时将它们交付给您的代码。

游戏通常会遇到这种情况。您可能已经注意到,游戏通常有一个固定的刷新率,他们称之为 FPS(每秒帧数)。通常保持 60 FPS 就足够了。也就是说,您需要每秒绘制 50 次 UI,但现在您的渲染循环(更新 UI)似乎在连续运行。

您需要有单独的线程持续运行,该线程负责绘制 UI。这应该绘制到缓冲区 (Image)。然后在要更新的 UI 元素上调用 repaint()。该 UI 元素的 paintComponent() 需要被覆盖,以便它可以复制 Image 缓冲区中的图像并将其绘制到图形上下文中。

现在真正的诀窍来了。调用repaint() 的循环必须做一些算术以确保它不会超过绘制 60 次,即每秒循环 60 次。如果它发生了,那么它必须调用Thread.sleep(sleepTime),其中sleepTime 是循环60 次后一秒钟内剩余的毫秒数。有时您的循环可能需要超过一秒钟才能完成 60 次迭代,然后不要只是继续进行下一次迭代,而是调用 Thread.yield()。这将使其他线程有机会使用 CPU,例如也许你的 EDT。让事情变得更复杂,不要总是让让,所以可能需要一些逻辑来确保让让只连续 x 次。如果有的话,最后一种情况应该是非常罕见的。这种情况意味着系统负载很重。

请记住,repaint() 是线程安全的,允许从任何线程调用。它在 EDT 上安排 paint() 通话。因此,致电repaint() 并不能保证油漆。因此,您可能需要尝试不同的 FPS 值来找到适合您的值。

顺便说一句,渲染到内存中Image 的技巧在技术上称为双缓冲区。这使我们能够渲染出漂亮流畅的动画。

延伸阅读:-

【讨论】:

  • 我明白你的意思,我经历了一些多线程 tuts(以前从未使用过)。但后来让我感到震惊的是,我可以在事件处理程序中简单地有一个布尔开关,由分散在要中断的方法长度中的几个 if 来查看。如果为真,它会抛出一个被整个方法范围的 try/catch 捕获的异常。在 catch 中,它使用通过鼠标单击修改的输入来重建 GUI。更简单:-)
  • 如果你有一个要被许多线程读取的布尔值,那么你必须将它标记为volatile。 ;-)
【解决方案2】:

你看过SwingWorker吗?它是一个简单的框架,可让您在后台运行计算并定期向 GUI 线程发布更新。

【讨论】:

  • @Hovercraft:这个问题清楚地提到了“我正在使用swing”。 (至少从 OP 在您最初发表评论后编辑问题开始)
猜你喜欢
  • 2014-04-15
  • 2012-12-16
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 2019-04-10
相关资源
最近更新 更多