【问题标题】:Drawing a pendulum's rotation over time in a JPanel在 JPanel 中随时间绘制钟摆的旋转
【发布时间】:2014-01-12 06:55:50
【问题描述】:

我试图在 JPanel 中描述摆臂随时间的演变。 摆有一个固定节点,另一个节点是根据固定的一个和从文件中获取的一些角度计算的。每隔 1 秒,我希望看到钟摆用新坐标重新绘制。 为了描述我的问题,我已经消除了文件和角度计算,请考虑将移动点保存到点的 ArrayList 中。

我试图通过在 RotateLine 对象的构造函数中调用 drawRotatingLine() 方法来实现随时间的逐渐旋转。 在 drawRotatingLine() 方法中,我有一个 for 循环:

  • 根据 ArrayList of Points 的值设置移动点的坐标
  • 引入 1 秒睡眠
  • 并调用repaint()方法

问题是我只让我的程序绘制初始位置,然后绘制最后一个位置,中间位置没有绘制。

代码从这里和那里放在一起非常不完整。请原谅我滥用了 BufferedImage、Graphics2D 以及在 paintComponent(...) 方法中对这些对象的调用对我来说并不完全清楚,我只需要完成程序,在我的经验阶段,我发现 JPanel 上的绘图非常复杂。

下面是整个代码:

public class RotateLine extends JPanel {

private static final int PREF_W = 600;
private static final int PREF_H = 600;
private static final int X1 = 100;
private static final int Y1 = 100;
private BufferedImage image;
private Graphics2D bufferedGraphics;
private static ArrayList<Point> pointsList;
private static Point p;
private int counter = 0;

public RotateLine () {
    pointsList = new ArrayList<Point>();
    p = new Point(X1, Y1);
    int X2 = 400;
    int Y2 = Y1;
    for (int count = 0; count < 4; count++) {
        pointsList.add(new Point(X2, Y2));
        X2 = X2 - 100;
        Y2 = Y2 + 100;
    }
    image = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_RGB);
    bufferedGraphics = image.createGraphics();
    drawRotatingLine();
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(PREF_W, PREF_H);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    bufferedGraphics.clearRect(0, 0, PREF_W, PREF_H);
    bufferedGraphics.setColor(Color.WHITE);
    bufferedGraphics.fillRect(0, 0, PREF_W, PREF_H);
    bufferedGraphics.setColor(Color.BLACK);
    bufferedGraphics.drawLine(X1, Y1, p.x, p.y);
    g.drawImage(image, 0, 0, this);
    Toolkit.getDefaultToolkit().sync();

}

public static void main(String[] args) {
    JFrame frame = new JFrame("clock");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new RotateLine());
    frame.pack();
    frame.setVisible(true);
}

public void drawRotatingLine() {
    for (int i = 0; i < pointsList.size(); i++) {
        p.x = pointsList.get(i).x;
        p.y = pointsList.get(i).y;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(Pendul.class.getName()).log(Level.SEVERE, null, ex);
        }
        repaint();
    }        
}

}

【问题讨论】:

    标签: java jpanel bufferedimage paintcomponent graphics2d


    【解决方案1】:

    您的问题很常见:​​您在 Swing 事件线程上调用 Thread.sleep(...),这将使您的整个应用程序进入睡眠状态。而是阅读并使用摆动计时器。在谷歌上搜索 Swing Timer 教程后,在此网站上搜索 Java Swing Timer Animation 以获取有关如何将其用于动画的不错示例。

    所以,

    • 将计时器的延迟设置为您希望动画具有的任何时间片延迟,但我建议不要小于 12 毫秒。
    • 在Timer的ActionListener的actionPerformed中,根据ArrayList of Points的值和一个index设置移动Point的坐标
    • 增加索引(非常重要)
    • 将索引修改为最大值
    • 调用重绘

    【讨论】:

      【解决方案2】:

      根据 Hovercraft Full of Eels 的回答,这就是我使用 Java Swing Timer Animation 更改初始代码的方式:

      public class RotateLine extends JPanel **implements ActionListener**{
      
      private static final int PREF_W = 800;
      private static final int PREF_H = 800;
      private static final int X1 = 100;
      private static final int Y1 = 100;
      private static ArrayList<Point> pointsList;
      private static Point p;
      private int counter = 0;
      private int index = 0;
      **Timer time = new Timer(10, (ActionListener) this);**
      
      public RotateLine () {
          pointsList = new ArrayList<Point>();
          p = new Point(X1, Y1);
          int X2 = 400;
          int Y2 = Y1;
          for (int count = 0; count < 300; count++) {
              pointsList.add(new Point(X2, Y2));
              X2 = X2 - 1;
              Y2 = Y2 + 2;
          }
          **time.start();**
      }
      
      @Override
      public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
      }
      
      @Override
      protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2d = (Graphics2D)g;
          drawRotatingLine(g2d);
      }
      
      public static void main(String[] args) {
          JFrame frame = new JFrame("clock");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.add(new RotateLine());
          frame.pack();
          frame.setVisible(true);
      }
      
      public void drawRotatingLine(Graphics2D g) {
          g.drawLine(p.x, p.y, pointsList.get(index).x, pointsList.get(index).y);        
      }
      
      **public void actionPerformed(ActionEvent arg0) {
        if (index < pointsList.size() - 1){
        time.setDelay(20);
        repaint();
        index++;
        }
      }**  
      

      【讨论】:

        猜你喜欢
        • 2018-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-05
        • 2012-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多