JFrame闪光图像1/100秒

时间:2015-01-11 23:56:38

标签: java image swing

我有JFrame,需要将图像闪烁10毫秒(或者显示器可以支持的最小值)。

目前,这就是我所做的:

我的 JFrame 带有 JPanel ,并带有覆盖的paintComponent()方法。当我需要闪现该图片时,我调用repaint()方法在 JFrame 上绘制图片,然后安排下一个再次调用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毫秒?

1 个答案:

答案 0 :(得分:2)

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

  • 调用setVisible与用户实际可见的时间之间的时间......
  • 设置事件调度线程的时间......
  • 设置Timer并安排TimerTask
  • 的时间
  • 请求重新绘制帧的时间与实际重绘的时间之间的时间
  • 您要求重新绘制帧的事实而不是实际显示图像的组件
  • 系统中的其他一些活动,包括Java API和/或操作系统......

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

因此,不是在调用TimerTask后直接安排setVisible,而是可以使用WindowListener,这样您可以在窗口打开时收到通知并启动计时器然后......

不要在调用main的线程中构建所有内容,而是确保在Event Dispatching Thread的上下文中创建和更新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();
                }
            }
        });
    }

}