用定时器绘图不工作

Drawing with timer is not working

我在 Java 中绘图时遇到问题。我认为我的代码是正确的,但是当我将它与计时器一起循环时,它不会打印任何内容。我想每秒重复 doDrawing(g) 方法。现在它只会打印文本舞会 system.out 但不会打印绘图。

package src;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.JPanel;
import javax.swing.Timer;

public class surface extends JPanel{

private void doDrawing(Graphics g){
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.black);

    //souradnice stredu ciferniku
    final int sx = 250;
    final int sy = 250;

    // inicializace promennych
    int uhel = 0;
    int delka = 150;
    int xHodina,xMinuta,xSekunda,
        yHodina,yMinuta,ySekunda;


    // získání aktuálního času
     int HOUR = Calendar.getInstance().get(Calendar.HOUR);
     int MINUTE = Calendar.getInstance().get(Calendar.MINUTE) + 1;
     int SECOND = Calendar.getInstance().get(Calendar.SECOND) + 1 ;

    //výpočet jednotlivých úhlů pro jednotlivé ručičky a jejich vykreslení
     xSekunda = (int) ((int) sx + Math.round( Math.sin(( 6 * SECOND * Math.PI / 180)) * delka));
     ySekunda = (int) ((int) sy - Math.round( Math.cos(( 6 * SECOND * Math.PI / 180)) * delka));


    //vyhreslení ručiček
     g2d.drawLine(sx, sy, xSekunda, ySekunda);

    //info             
     System.out.print(" "+(6 * SECOND)+ "  "+ HOUR+"  "+MINUTE+"  "+SECOND+"     "+xSekunda+" "+ySekunda+"\n");
    }

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);

    int delay = 1000; //milliseconds
    //Somewhere there is that problem .. 

      ActionListener taskPerformer = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              doDrawing(g);
          }
      };
      new Timer(delay, taskPerformer).start();
}   
}

问题就在这里。

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);

    int delay = 1000; //milliseconds
    //Somewhere there is that problem .. 

      ActionListener taskPerformer = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              doDrawing(g);
          }
      };
      new Timer(delay, taskPerformer).start();
    }   
}

切勿在 paintComponent 内部启动计时器。此方法只画画不画,我的意思绝对没有别的。

您应该在其他地方启动您的计时器,也许在 class 的构造函数中,并让它更改您的 class 的字段,然后调用 repaint()。然后 paintComponent 方法应该使用这些字段来决定绘制什么和在哪里绘制。

例如,您的 doDrawing() 方法(没有 Graphics 参数)可以创建一个 Line2D,将其添加到 List<Line2D>,然后调用 repaint()paintComponent(...) 方法然后可以遍历此列表绘制每一行:

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.Timer;

public class surface extends JPanel {

   private List<Line2D> lineList = new ArrayList<>();

   public surface() {
      int delay = 1000; // milliseconds
      // Somewhere there is that problem ..

      ActionListener taskPerformer = new ActionListener() {
         public void actionPerformed(ActionEvent evt) {
            doDrawing();
         }
      };
      new Timer(delay, taskPerformer).start();
   }

   private void doDrawing() {

      // souradnice stredu ciferniku
      final int sx = 250;
      final int sy = 250;

      // inicializace promennych
      int uhel = 0;
      int delka = 150;
      int xHodina, xMinuta, xSekunda, yHodina, yMinuta, ySekunda;

      // získání aktuálního času
      int HOUR = Calendar.getInstance().get(Calendar.HOUR);
      int MINUTE = Calendar.getInstance().get(Calendar.MINUTE) + 1;
      int SECOND = Calendar.getInstance().get(Calendar.SECOND) + 1;

      // výpočet jednotlivých úhlů pro jednotlivé ručičky a jejich vykreslení
      xSekunda = (int) ((int) sx + Math.round(Math
            .sin((6 * SECOND * Math.PI / 180)) * delka));
      ySekunda = (int) ((int) sy - Math.round(Math
            .cos((6 * SECOND * Math.PI / 180)) * delka));

      Line2D line = new Line2D.Double(sx, sy, xSekunda, ySekunda);
      lineList.add(line);
      repaint();

      // info
      System.out.print(" " + (6 * SECOND) + "  " + HOUR + "  " + MINUTE + "  "
            + SECOND + "     " + xSekunda + " " + ySekunda + "\n");
   }

   @Override
   public void paintComponent(final Graphics g) {
      super.paintComponent(g);
      Graphics2D g2d = (Graphics2D) g;
      g2d.setColor(Color.black);

      for (Line2D line2d : lineList) {
         g2d.draw(line2d);
      }

   }
}

Edit 不好意思,您只想使用此代码绘制 one 行,而不是行列表。如果是这样,摆脱列表,而是创建一个 Line2D 字段,该字段由您的计时器更改并由您的 paintComponent 绘制:

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Double;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

// !! Class names should begin with upper-case letter
public class Surface extends JPanel {
   private static final double DELKA = 150;
   private static final int SX = 250;
   private static final int SY = SX;
   private static final int DELAY = 1000;
   // private List<Line2D> lineList = new ArrayList<>();
   private Timer timer = new Timer(DELAY, new TaskPerformer());
   private Line2D line;

   public Surface() {
      timer.start();
   }

   private void doDrawing() {
      int xSekunda, ySekunda;

      int HOUR = Calendar.getInstance().get(Calendar.HOUR);
      int MINUTE = Calendar.getInstance().get(Calendar.MINUTE) + 1;
      int SECOND = Calendar.getInstance().get(Calendar.SECOND) + 1;

      xSekunda = (int) ((int) SX + Math.round(Math
            .sin((6 * SECOND * Math.PI / 180)) * DELKA));
      ySekunda = (int) ((int) SY - Math.round(Math
            .cos((6 * SECOND * Math.PI / 180)) * DELKA));

      // Line2D line = new Line2D.Double(SX, SY, xSekunda, ySekunda);
      line = new Line2D.Double(SX, SY, xSekunda, ySekunda);
      // lineList.add(line);
      repaint();

      // info
      System.out.print(" " + (6 * SECOND) + "  " + HOUR + "  " + MINUTE + "  "
            + SECOND + "     " + xSekunda + " " + ySekunda + "\n");
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(2 * SX, 2 * SY);
   }

   @Override
   public void paintComponent(final Graphics g) {
      super.paintComponent(g);
      Graphics2D g2d = (Graphics2D) g;
      g2d.setColor(Color.black);

      // to give smoother lines
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      // iterate through our list and draw lines it holds
      if (line != null) {
         g2d.draw(line);
      }

   }

   private class TaskPerformer implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         if (!isShowing() && timer != null && timer.isRunning()) {
            timer.stop();
         } else {
            doDrawing();
         }
      }
   }

   private static void createAndShowGui() {
      Surface mainPanel = new Surface();

      JFrame frame = new JFrame("surface");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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