调整窗口/ JFrame的大小会导致计时器滞后

时间:2013-11-30 13:42:26

标签: java swing timer paintcomponent

我有一个非常基本的JPanel,它设置在自己的JFrame

JPanel implements actionlisteneroverrides paintcomponent

我在paintcomponent方法中绘制了一堆东西,只是形状和多边形,大多数是固定的,但是旋转的是2个组件。这是通过计时器完成的。 计时器是Swing Timer;

修正后我的意思是没有可能影响其位置的变量。

该类有一个启动计时器的StartTimer (StartTheCountdown())方法。在每个计时器勾选时,执行的操作是它将角度增加一个固定的数字,然后它要求重新绘制窗口。 这是为了旋转未修复的几个组件。 (我在代码中留下了你要看的内容)

我遇到的问题是,如果你调整窗口大小,它会导致计时器滞后,因此旋转不会在适当的时间内发生。当你停止调整大小时,它会恢复正常。

如果你只是做一个快速的单一拖动并调整其大小不明显,但只是为了测试,如果我点击并按住并在屏幕上疯狂地拖动几秒钟,当我放开它显着滞后时,几乎就像它来到停下来,只有当我放手时才会继续。

我读过有关使用不同线程绘制和执行某些任务的信息,SwingWorker?但我不太确定如何在我的情况下使用它。

有关如何防止这种滞后的任何提示?

编辑:我添加了准备编译并按原样运行的新代码。

如果让它继续运行,箭头会在30秒后停在底部。如果你持续调整窗口大小一秒左右,计时器会在30秒后停滞不前,它还没到达底部。调整大小时的这种滞后是我试图阻止的。

    import java.awt.* ; 
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;

class guidemo{  

    JFrame clockscreen = new JFrame();
    JPanel clockpanel = new JPanel(new GridLayout(1,1));

    Theclock clock ;

    guidemo ()
    {   

        clock = new Theclock();
        clockscreen.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        clockscreen.setTitle( "Countdown" );
        clockscreen.setLocation(0,0);      
        clockscreen.setSize(830,830); 
        clockscreen.add(clockpanel);
        clockpanel.add(clock);

        clockscreen.setVisible(true);        

        clock.StartTheCountdown();
    }

    public static void main(String[]args) 
    {       
        //Setup demo
        guidemo demo = new guidemo();

    }
}



class Theclock extends JPanel implements ActionListener
{

    Timer clockticker = new Timer(40,this);
    double theta = 0;

    public void StartTheCountdown(){
        clockticker.start();
    }

    public void StopTheCountdown(){
        clockticker.stop();
    }

    public void paintComponent(Graphics gc)
    {
        super.paintComponent(gc);
        Graphics2D g2d = (Graphics2D)gc;
        AffineTransform tx = new AffineTransform();

            /*
        There are lots of other graphics being drawn here 
        like ovals and rectangles etc but they are not affected 
        by the incrementing theta. So I removed them. 
        */

        tx.rotate((double)theta*(3.14/180), 400, 400);
        g2d.setTransform(tx);

        //Arrow border
        g2d.setColor(new Color(159,131,154));
        Polygon p = new Polygon();
        p.addPoint(350,400);
        p.addPoint(400,200);
        p.addPoint(450,400);
        g2d.fill(p);

    }

    public void actionPerformed(ActionEvent e)
    {
        theta += 0.25;
        System.out.println(theta);
        this.repaint();

        if(theta == 180){
            StopTheCountdown();
        }
    }

}

2 个答案:

答案 0 :(得分:2)

  

有关如何防止这种滞后的任何提示?

将动画的静态部分存储在BufferedImage中。在绘画时,绘制图像,然后将旋转的部分添加到顶部。

答案 1 :(得分:1)

我在Windows 7上使用JDK7时没有注意到任何问题。当我不断调整框架大小时,对象会继续旋转。这可能是版本/平台问题。

如果没有重新绘制那么问题可能是EDT滞后而且并非所有事件都是由Timer生成的,因为默认是使用setCoalesce(true),如果EDT滞后,它会将多个事件组合成一个

所以你可以尝试使用:

timerClock.setCoalesce(false);

如果这不起作用,那么您可以手动管理适当的旋转角度。这不仅仅是每次计时器触发时都添加0.25。

相反,您可以保持计时器启动的计时器。当计时器触发时,您将获得当前时间,并根据自计时器启动以来经过的时间确定适当的角度。这样,如果EDT陷入困境,当下一个Timer事件被触发时,你将“跳转”到适当的位置。