JFrame flash 图像 1/100 秒

JFrame flash image for 1/100 second

我有 JFrame,需要闪烁图像 10 毫秒(或显示器可以支持的最短时间)。

目前,这是我所做的:

我有一个 JFrame 和一个 JPanel 并覆盖了 paintComponent() 方法。当我需要刷新该图像时,我调用 repaint() 方法在 JFrame 上绘制图像,然后安排 next 再次调用 repaint() 以删除10 毫秒后的图像。但是它会发出很长的闪光,肉眼很明显。

这是我的代码:

public static boolean show = true;

public static void main(String[] args) {
    final JFrame f = new JFrame("Test");
    f.setUndecorated(true);
    f.setAlwaysOnTop(true);
    f.setFocusable(false);
    JPanel c = new JPanel() {

        @Override
        public void paintComponent(Graphics g) {
            if (show) {
                try {
                    // I was too lazy to save the image as a variable ;)
                    g.drawImage(ImageIO.read(ClassLoader.getSystemResource("Puppy.png")), 1, 1, null);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            super.paintComponent(g);
        }
    };
    c.setOpaque(false);
    c.setPreferredSize(new Dimension(1920, 1080));
    f.getContentPane().add(c);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.pack();
    f.setVisible(true);
    com.sun.awt.AWTUtilities.setWindowOpaque(f, false);

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            long time = System.nanoTime();
            show = true;
            f.repaint();
            timer.schedule(new TimerTask() {

                @Override
                public void run() {
                    show = false;
                    f.repaint();
                    System.out.println(System.nanoTime() - time + Boolean.toString(show));
                }
            }, 10);
        }
    }, 1000, 1000);
}

问:为什么帧闪那么久,10毫秒都没有?

可能会发生很多事情...

  • 调用 setVisible 和帧对用户实际可见的时间之间的时间...
  • 设置事件调度线程的时间...
  • 设置 Timer 和安排 TimerTask
  • 的时间
  • 请求重绘帧与重绘实际发生之间的时间
  • 您请求重新绘制框架而不是实际显示图像的组件这一事实
  • 系统上的其他一些activity,都在JavaAPIand/orOS...

您需要尝试缓解其中一些问题...

因此,不是在调用 setVisible 之后直接安排 TimerTask,而是可以使用 WindowListener,以便在 window 打开并开始时通知您然后计时器...

不要在调用 main 的线程中构建所有内容,而是确保从事件调度线程

的上下文中创建和更新 UI

不要在框架上调用 repaint,而是尝试重新绘制您想要重新绘制的实际组件...

而不是使用java.util.Timer,使用javax.swing.Timer,在修改UI

的状态时更安全

以下示例简单地使用 JLabel 渲染图像并在 javax.swing.Timer 滴答后将其删除...

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 *
 * @author shane
 */
public class Test {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                try {
                    BufferedImage img = ImageIO.read(new File("C:\hold\thumbnails\_MTCGAC__Pulling_Cords_by_Dispozition.png"));
                    JLabel label = new JLabel(new ImageIcon(img));

                    JFrame frame = new JFrame("Testing");
                    frame.addWindowListener(new WindowAdapter() {
                        @Override
                        public void windowOpened(WindowEvent e) {
                            Timer timer = new Timer(10, new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    frame.remove(label);
                                    frame.revalidate();
                                    frame.repaint();
                                }
                            });
                            timer.setRepeats(false);
                            timer.start();
                        }
                    });
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(label);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

}