延迟在java图形中不起作用

这是通过Bresenham算法在计算位置上绘制点的代码:

public void drawBresenhamPoints(Graphics2D g2, List bresenham) throws InterruptedException { Graphics2D g = (Graphics2D) g2; if(bresenham == null) return; g.setColor(Color.DARK_GRAY); for(int i = 0; i < bresenham.size(); i = i+20) { int x = bresenham.get(i).x - pointWidth1/2; int y = bresenham.get(i).y - pointWidth1/2; int ovalW = pointWidth1; int ovalH = pointWidth1; g.fillOval(x, y, ovalW, ovalH); // delay try { Thread.sleep(10); } catch(Throwable e) { System.out.println(e.getMessage()); } } } 

列表’bresenham’包含在Bresenham的线绘制算法的帮助下预先计算的所有点。 我想在’for’循环内设置1秒的延迟,以便在1秒的间隔后绘制每个点。 “延迟”部分中列出的部分不起作用。 如何使’延迟’工作? 更具体地说,我想看到所有的点在屏幕上以1秒的间隔逐个绘制。

我假设您在paint/paintComponent方法中调用此方法。

只是一个指针: 从来没有睡过油漆过程

而是使用javax.swing.Timer来执行重复的任务。 会做的是

  • 有两个Lists 。 你的List bresenham List paintList和另一个List paintListpaintList将保存您的数据, paintList最初将为空。

  • 使用paintList绘制您的点

     @override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; for (Point p : paintList) { int x = bresenham.get(i).x - pointWidth1/2; int y = bresenham.get(i).y - pointWidth1/2; int ovalW = pointWidth1; int ovalH = pointWidth1; g.fillOval(x, y, ovalW, ovalH); } } 
  • 尽管最初在paintList没有任何paintList ,但每次触发计时器事件时,都会向列表中添加一个新Point

     Timer timer = new Timer(100, new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { if (bresenham.isEmpty()) { ((Timer)e.getSource()).stop(); } else { paintList.add(bresemham.get(0)); bresenham.remove(0); } repaint(); } }); timer.start(); 

    构造函数的基本计时器是delay ,即“迭代”之间延迟的时间,以及侦听器中实际侦听每delay毫秒触发的计时器事件的第二个参数。 那么上面代码基本上做的是将一个Point添加到从paintList列表中获取的paintList ,然后删除调用paintComponentrepaint项。 当列表为空时,计时器将停止。


UPDATE

这是一个完整的运行示例

 import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.Timer; public class BresenhamPoints extends JPanel { private static final int D_W = 500; private static final int D_H = 500; private List bresenhamList; private List paintList; public BresenhamPoints() { bresenhamList = createRandomPoints(); paintList = new ArrayList<>(); Timer timer = new Timer(100, new ActionListener() { public void actionPerformed(ActionEvent e) { if (bresenhamList.isEmpty()) { ((Timer) e.getSource()).stop(); } else { paintList.add(bresenhamList.get(0)); bresenhamList.remove(0); } repaint(); } }); timer.start(); } private List createRandomPoints() { Random rand = new Random(); List list = new ArrayList<>(); for (int i = 0; i < 100; i++) { list.add(new Point(rand.nextInt(D_H), rand.nextInt(D_H))); } return list; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); for (Point p : paintList) { g.fillOval(px - 5, py - 5, 10, 10); } } @Override public Dimension getPreferredSize() { return new Dimension(D_W, D_H); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JFrame frame = new JFrame(); frame.add(new BresenhamPoints()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } } 

sleep方法的值以毫秒为单位 ,因此您正在睡眠10ms。 将其更改为1000将创建更明显的中断。

正如所指出的那样,你不应该在EDT上花费任何时间或甚至更糟的锁定机制,因为它会挂起你的整个应用程序。 您可以使用Timer来触发事件并一次绘制一个点。 这个以前的SOpost应该做你需要的。