2

我编写了一个用于操作读卡器的 GUI——主要由一个 ADD 按钮组成,该按钮会弹出一个FileChooser对话框并将选择的内容排队File到 CardHopper 上,它在视觉上显示为JList.

现在我希望 CPU(另一个JFrame,在另一个线程上)能够向读卡器发出请求;例如,读一张卡片并发送给我。在读卡器有 GUI 之前,它只是一个与 CPU 运行在同一线程上的模型,所以我可以调用它的readCard()方法。现在它在一个单独的线程上,似乎正确的通信方式是使用消息传递。

我正要使用 a 来实现一些东西PriorityBlockingQueue,CPU 将put在队列上执行读卡命令,而 CardReader 将take执行该命令,直到我意识到 CardReader 线程通常会在其 NetBeans 提供的 Swing 代码中的某处被阻塞,等待 GUI 事件并且对我的事件队列中的任何内容的到来视而不见。此外,这个“后端”请求会改变数据模型——所以即使我ListDataListeners以某种方式在模型中执行一些代码,在 GUI 等待 GUI 事件时向 GUI “触发”通知是否合乎情理?

我希望这不是太神秘 - 我仍然试图让我的手臂围绕 GUI 和线程的机制。

4

1 回答 1

4

当 GUI 等待 GUI 事件时,向 GUI 的 ListDataListeners “触发”通知是否符合规定?

绝对不。

您要做的是在 Swing 事件线程上执行所有直接操作 UI 模型(或调用 UI 函数)的任务。

本质上,当您准备发布将执行某些 UI 任务的事件时,请执行以下操作:

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
     ...
  }
}

您可以触发所有侦听器,并对您的 ListModel(或您的其他 UI 模型)执行任何您想要的操作,因为它只会在 Swing 线程中运行。

否则,您可能会冒着 Swing 在绘画和更新数据时尝试读取数据的风险。您将开始收到 NullPointerException、ArrayIndexOutOfBoundExceptions、ConcurrentModifictionException 等。

理想情况下,您将在一个单独的线程中(或在 SwingWorker 下)执行所有后台工作,然后当一切准备就绪时,通过 invokeLater 推送更新。

于 2011-07-18T20:23:43.663 回答