有没有办法从异步方法绘制到 JPanel 上?



我正在使用Swing和Firebase编写一个基于Java的游戏。我将所有玩家存储在一个列表中,当其中任何一个移动时,onChildChanged(...)回调(见下文)就会被触发。由于这是异步的,我显然无法设置任何超出函数范围的变量。这一切都很好,直到我需要真正将这个播放器绘制到屏幕上。

由于我扩展了JPanel并覆盖了它paintComponent(Graphics g)因此我必须在此方法中完成所有绘图(或者至少这是我被告知的)。问题是我需要从回调内部绘制这个播放器,这就是我不知道该怎么做的。

我尝试将Graphics g对象"导出"到全局变量,然后在异步函数中使用该变量,但这没有产生任何结果。也许是因为它实际上并没有吸引到JPanel的画布上?

所以我有一堂这样的课:

class Screen extends JPanel {
@Override
public void paintComponent(Graphics g) {
// All my painting stuff goes here
}
ref.addChildEventListener(new ChildEventListener() {
// This is the callback
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
// Draw the player
}
}
});
}

编辑:忘了提到我也在每场比赛滴答声中调用repaint()(每秒60次)。我不知道这是否会改变什么,但以防万一:)

所以我希望能够在回调中绘制播放器或在paintComponent()方法中绘制它,我想知道如何做到这一点。

谢谢!

除了在paintComponent方法中之外,您不应该在任何地方绘制。所以解决方案是:

  • 更新用于告知 GUI 要绘制的内容的模型字段。
  • 如果此更新将以任何其他方式直接影响 GUI,例如更新文本字段、标签、JTables 等,则应在 EDT 上执行此数据更改,方法是将其放入传递到SwingUtilities.invokeLater(...)的 Runnable 中的事件队列中
  • 然后打电话给repaint()
  • 然后,GUI 将使用这些字段并在 Swing 事件线程上执行所有绘制。

请注意,repaint()是少数可以从 EDT调用的 Swing 方法之一。


我对你更新模型字段是什么意思有点困惑,哈哈,你能澄清一下吗?

如果要创建任何复杂的 GUI,则可能会使用模型 - 视图类型的结构(例如用于模型-视图-控制器的 M-V-C),其中您将程序逻辑、模型部分与 GUI 和视图分开。该视图描述了模型的状态并允许用户交互,所以我谈论的是状态字段。

例如,如果您有一个带有动画的游戏,该模型将表示玩家的位置、玩家的状态(健康、武器、库存)、他们的行为......而视图将根据模型的状态绘制所有这些。

最新更新