java闪烁对象,频率稳定

java闪烁对象,频率稳定,java,swing,frequency,Java,Swing,Frequency,我发现的所有其他问题似乎都与“无闪烁”有关,而我实际上想要一个闪烁 我正试图建立一个小应用程序,显示对象闪烁在一个给定的频率 下面是我正在尝试做的一个小的可行的例子。当前,我通过以给定频率执行的计划任务闪烁对象。在此任务中,我绘制对象,等待一半时间,然后删除它。这应该给我一个物体,它以给定的频率闪烁 然而,我发现即使在低至4Hz的频率下,闪烁也不再稳定。我认为这是因为Java不能保证在被要求时绘制屏幕,但允许它将某些绘制任务合并成一个。我不确定,但我想我读过类似的东西 我的问题是:如何制作一个频

我发现的所有其他问题似乎都与“无闪烁”有关,而我实际上想要一个闪烁

我正试图建立一个小应用程序,显示对象闪烁在一个给定的频率

下面是我正在尝试做的一个小的可行的例子。当前,我通过以给定频率执行的计划任务闪烁对象。在此任务中,我绘制对象,等待一半时间,然后删除它。这应该给我一个物体,它以给定的频率闪烁

然而,我发现即使在低至4Hz的频率下,闪烁也不再稳定。我认为这是因为Java不能保证在被要求时绘制屏幕,但允许它将某些绘制任务合并成一个。我不确定,但我想我读过类似的东西

我的问题是:如何制作一个频率高达屏幕刷新率一半的稳定闪烁对象

public class NewJFrame extends javax.swing.JFrame {

private final int FlashFreqHz = 4;
private java.util.Timer timer;
/**
 * Creates new form NewJFrame
 */
public NewJFrame() {
    initComponents();
    startFlashing();
}
private class FlashingTask extends TimerTask{
    @Override
    public void run() {
        int w=jPanel1.getWidth();
        int h=jPanel1.getHeight();
        try {
            jPanel1.getGraphics().fillRect(10, 10, w/2, h/2);
            Thread.sleep((1000/FlashFreqHz)/2);
            jPanel1.getGraphics().clearRect(10, 10, w/2, h/2);
        } catch(InterruptedException ex) {
            ex.getStackTrace();
        }
    }
}
public void startFlashing() {
    if(timer!=null) stopFlashing(); //  running, must stop to get new position correct

    timer = new java.util.Timer();
    timer.scheduleAtFixedRate(new FlashingTask(), 0, 1000/FlashFreqHz); // 40 ms delay
}
public void stopFlashing() {
    if (timer != null) {
        timer.cancel();
        timer = null;
        jPanel1.repaint();
    }
}

请检查,以下是我的“更正”代码:

import java.awt.event.ActionEvent;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import java.awt.Graphics;

public class NewJFrame extends javax.swing.JFrame implements ActionListener{
private final int FlashFreqHz = 60;
private final Timer timer;
private boolean Flash = false;
FlashFrame FlashPanel;
/**
 * Creates new form NewJFrame
 */
public NewJFrame() {
    initComponents();
    FlashPanel = new FlashFrame();
    setContentPane(FlashPanel);
    timer = new Timer(1000/FlashFreqHz,this);
    timer.start(); 

}
class FlashFrame extends JPanel {
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);       
        if(Flash) {
            g.fillRect(10, 10, getWidth()/2, getHeight()/2); 
        } else {
            g.clearRect(10, 10, getWidth()/2, getHeight()/2); 
        }
    }
}
@Override
public void actionPerformed(ActionEvent e) {
    FlashPanel.repaint();
    Flash = !Flash;
}
你觉得这个更好吗

我开始的问题也是遗留问题。虽然频率比我的“睡眠”方法稳定得多,但仍然存在一些明显的不稳定性,尤其是在更高的频率下


有什么可以做的吗?

Thread.sleep()是一种固有的不稳定的计时方式,它不仅取决于它的运行方式,而且如果操作系统决定让jvm线程休眠一秒钟,Thread.sleep()任务将看不到使用getGraphics不是自定义绘制的方式。使用Java.util.Timer违反了Swing的单线程规则。看一看,您的更新代码很好。如果您仍然注意到不稳定性(顺便问一下,频率是多少?),这可能与摆动绘画机制无关。我的经验是,Swing每秒能够处理数千个事件,因此,当给定一个简单的绘制任务时,异步重新绘制能够获得非常高的帧速率(远大于监视器刷新)。实际上,我想到了一件可以尝试的事情,那就是调用计时器<默认情况下,code>javax.swing.Timer合并操作事件。虽然我不认为这真的会有多大区别,但我敢打赌你仍然在尝试高于显示器刷新率的频率(无论你做什么都无法显示)。嗨,谢谢你的回复,我将测试“合并”的想法,谢谢。监视器刷新率为60Hz,即使在20Hz闪烁率下,也会出现小的不连续性。正如我之前所说的,它现在好多了,可能还可以接受,我只是想知道它是否可以更容易地进一步改进。当然,将闪烁率提高到60Hz以上会产生虚假的结果:D