【问题标题】:Custom Drawing loop in SwingSwing 中的自定义绘图循环
【发布时间】:2014-09-08 08:14:11
【问题描述】:

我正在尝试学习如何在 Java 中为我正在处理的一个小组项目做自定义 GUI 的东西。我过去做过用户表单类型的 GUI,所以我知道我在这里做的事情的要点,但是自定义绘图的东西仍然让我感到困惑。

我从网上复制了这段代码,我一直在试图弄清楚它是如何工作的,但我不明白为什么我不能循环绘制方法。作为一个简单的测试,我试图让程序在我的光标上绘制一个椭圆。它在光标上绘制椭圆,但只在运行时绘制一次,然后什么也不做。

我怎样才能使这个循环,以便我可以继续画东西?或者我需要以其他方式调用/使用这些方法吗?

public class BombermanGUI extends JFrame {
   public static final int CANVAS_WIDTH  = 640;
   public static final int CANVAS_HEIGHT = 480;

   private DrawCanvas canvas;

   public BombermanGUI() {
      canvas = new DrawCanvas();  
      canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));

      Container cp = getContentPane();
      cp.add(canvas);

      this.setDefaultCloseOperation(EXIT_ON_CLOSE);  
      this.pack();             
      this.setTitle("......"); 
      this.setVisible(true);    
   }

   private class DrawCanvas extends JPanel{
      @Override
      public void paintComponent(Graphics g){
         super.paintComponent(g);  
         setBackground(Color.BLACK); 

         int x, y;
         x = MouseInfo.getPointerInfo().getLocation().x - this.getLocationOnScreen().x;
         y = MouseInfo.getPointerInfo().getLocation().y - this.getLocationOnScreen().y;
         g.setColor(Color.YELLOW);    
         g.drawOval(x, y, 10, 10);

      }
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            new BombermanGUI(); 
         }
      });
   }
}

【问题讨论】:

  • 添加一个事件监听器并让它调用repaint 方法,例如用于跟踪鼠标光标的鼠标运动侦听器,或者让某个线程运行您的游戏并定期触发 repaint
  • 哎呀,我在删除不必要的位时把代码搞砸了,现在就修复它
  • 还可以查看TimerBasedAnimation 的想法。
  • 啊,重绘是我一直在寻找的,应该可以解决我的问题。感谢您的建议 davidpostill。没有答案,所以我无法选择最佳答案...

标签: java swing loops graphics drawing


【解决方案1】:

绘制一系列复杂的回调和对系统内变化的响应。首先要记住的是,您不控制绘画过程,而是向系统提出建议,以便它可以决定应该重绘什么以及何时重绘......

查看Painting in AWT and SwingPerforming Custom Painting 了解更多详情。

绘画是一个破坏性的过程。假设当发生重绘时,您将重绘当前组件的整个状态。这意味着您将需要某种模型来维护所有需要绘制的内容...

看看2D Graphics,特别是看看Shape上的部分

MouseInfo 是一种非常糟糕的方法来检测鼠标的位置,相反,您应该使用MouseListener and/or MouseMotionListener 来检测鼠标事件。

基本上,当用户按下鼠标按钮时,您会记录鼠标按下的位置。当鼠标移动时,您将计算移动相对于鼠标按下的宽度和高度,并更新“当前”形状。您可以调用 repaint 请求更新 UI 并通过 paintComponent 方法绘制此形状(首先绘制所有先前的形状)。

当释放鼠标按钮时,您会将“当前”形状提交给模型,因此每次调用 paintComponent 时都会绘制它。

【讨论】:

  • 哇,这让我头疼不已。幸运的是,我有时间弄清楚这一切,谢谢
  • @user2856410 从概念上讲,它真的很简单(无意冒犯,我知道它看起来很复杂),问题是,这是一个非线性问题,因为您在事件驱动的环境中运行,所以您需要维护从一个事件到下一个事件的“有状态”细节,这些细节并不总是直接相关
【解决方案2】:

这是 tobais_k 回答 IM 回答以结束问题!

添加一个事件监听器并让它调用 repaint 方法,例如用于跟踪鼠标光标的鼠标运动侦听器,或者让某个线程运行您的游戏并定期触发重绘。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多