Java 定时器在不应该重复的时候重复

标签 java swing fullscreen paint timing

我想制作一个程序,在屏幕上显示一些图片以及字符串和动画。我是这样做的:

package Package;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class runScreen extends JFrame 
{
    public static void main(String[] arg) 
    {
        DisplayMode dm = new DisplayMode(1920, 1080, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
        runScreen b = new runScreen();
        b.getContentPane().setBackground(Color.CYAN);
        b.startScreen(dm);
    }
    private Screen s;
    private Image logo;
    private Image animation1;
    private Image animation2;
    private Image animation3;
    private boolean isLoaded;
    private static int testTime=5000;
    public void startScreen(DisplayMode dm) 
    {
        setForeground(Color.blue);
        setFont(new Font("Agency FB", Font.PLAIN, 50));
        isLoaded=false;
        s=new Screen();
        s.setFullScreen(dm, this);
        loadGraphics();
        Timer timer = new Timer(testTime, new ActionListener() 
        {
            @Override
            public void actionPerformed(ActionEvent e) 
            {
                s.restoreScreen();
            }
        });
        timer.setRepeats(false);
        timer.start();
    }
    private void loadGraphics() 
    {
        logo= new ImageIcon("C:\\test\\Atom.png").getImage();
        animation1=new ImageIcon("C:\\test\\Red.png").getImage();
        animation2=new ImageIcon("C:\\test\\Green.png").getImage();
        animation3=new ImageIcon("C:\\test\\Blue.png").getImage();
        isLoaded=true;
        repaint();
    }
    public void paint(Graphics g) 
    {
        super.paint(g);
        if(g instanceof Graphics2D)
        {
            Graphics2D g2=(Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        }
        if(isLoaded)
        {
            g.drawImage(logo,850,100,null);
            g.drawString("Atom", 900, 500);
            boolean canAnimationRun=true;
            int animationTime=0;
            while(canAnimationRun)
            {
                if(animationTime<testTime && canAnimationRun)
                {
                    g.drawImage(animation1,850,800,null);
                    try{Thread.sleep(1000);}
                    catch(Exception e){e.printStackTrace();}
                    animationTime+=1000;
                }else{canAnimationRun=false;}
                if(animationTime<testTime && canAnimationRun)
                {
                    g.drawImage(animation2,850,800,null);
                    try{Thread.sleep(1000);}
                    catch(Exception e){e.printStackTrace();}
                    animationTime+=1000;
                }else{canAnimationRun=false;}
                if(animationTime<testTime && canAnimationRun)
                {
                    g.drawImage(animation3,850,800,null);
                    try{Thread.sleep(1000);}
                    catch(Exception e){e.printStackTrace();}
                    animationTime+=1000;
                }else{canAnimationRun=false;}
            }
        }
    }
    public class Screen 
    {
        GraphicsDevice videoCard;
        public Screen() 
        {
            GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
            videoCard = env.getDefaultScreenDevice();
        }
        public void setFullScreen(DisplayMode dm, JFrame window) 
        {
            window.setUndecorated(true);
            window.setResizable(false);
            videoCard.setFullScreenWindow(window);
            if (dm!=null && videoCard.isDisplayChangeSupported()) 
            {
                try{videoCard.setDisplayMode(dm);}
                catch (Exception e){e.printStackTrace();}
            }
        }

        public Window getFullScreenWindow() 
        {
            return videoCard.getFullScreenWindow();
        }
        public void restoreScreen() 
        {
            Window w = videoCard.getFullScreenWindow();
            if (w != null) 
            {
                w.dispose();
            }
            videoCard.setFullScreenWindow(null);
        }
    }
}

但是时间上有问题;即使我设置了它应该运行的时间(参见testTime),它总是运行两倍的时间!这是什么原因?

最佳答案

  1. 不要直接在框架上进行自定义绘画。将 JPanel 添加到框架并重写面板的 PaintComponent() 方法以进行自定义绘画

  2. 不要在绘画方法中使用Thread.sleep()。

  3. 不要在绘制方法中使用 while 循环。 Paint方法用于绘制逻辑,不应包含程序逻辑

不知道这些建议是否能解决问题,但这是一个起点。

此外,传递给绘画方法的图形对象将是 Graphics2D 对象,因此您不需要 instanceof 检查。

关于Java 定时器在不应该重复的时候重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20955438/

相关文章:

java - 当我的应用程序启动时播放音频剪辑。

java - Android SQLite 查询

java - JPanel 内的 JPanel 的 JScrollPane

java - 陷入 JavaFX ListView 困境

jquery - jQuery:请求全屏在iPhone,iPad上不起作用

android - 尽管出现了弹出窗口、覆盖层或对话框,但如何隐藏导航栏?

android - 使用 camera2 api 在前置摄像头中全屏录制视频

java - 创建 JsonArray

java - 有没有办法增加netty中的DNS缓存TTL?

java - 这是将 MVC 用于多个 View 的好方法吗?