此样本不断绘制各种颜色的正方形。平方数基于JFrame的大小。
在执行示例时,使用鼠标放大或缩小尺寸框,它将增加或减少可见闪烁方块的数量。
帧的时间栏显示时间。此示例在draw()例程中还具有System.out.println。
目标不是要讨论此示例的编写水平如何,而是要用作提出问题的工具。
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class LotsOfSquares extends JPanel
{
Random rand = new Random();
static JFrame frame = new JFrame("Lots Of Squares ");
int numOfSquares = 0;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int sizeOfSquare = 5;
numOfSquares = 0;
for (int x=0; x<frame.getSize().width; x = x + sizeOfSquare )
{
numOfSquares ++;
for (int y=0; y<frame.getSize().height; y = y + sizeOfSquare )
{
g2d.setColor(new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
g2d.fillRect(x, y, sizeOfSquare, sizeOfSquare);
numOfSquares ++;
System.out.println(" Displaying " + numOfSquares + " squares within Inner Loop");
}
}
//System.out.println(" Displaying " + numOfSquares + " squares total");
}
public static void main(String[] args)
{
LotsOfSquares rects = new LotsOfSquares ();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(rects);
frame.setSize(360, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
TimerTask repeatedTask = new TimerTask()
{
public void run()
{
//System.out.println("Task performed on " + new Date());
frame.repaint();
}
};
Timer timer = new Timer("Refresh Timer");
long delay = 1000L;
long period = 150L;
timer.scheduleAtFixedRate(repeatedTask, delay, period);
TimerTask clockTask = new TimerTask()
{
public void run()
{
SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm:ss");
Calendar currentCalendar = Calendar.getInstance();
Date currentTime = currentCalendar.getTime();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
frame.setTitle(timeFormat.format(currentTime) );
}
});
}
};
Timer clockTimer= new Timer("Clock Timer");
long clockDelay = 1000L;
long clockPeriod = 1000L;
clockTimer.scheduleAtFixedRate(clockTask, clockDelay, clockPeriod);
}
}
程序启动时,框架很小,方框以恒定速率闪烁,时钟按时滴答滴答,并且System.out命令正在正常输出。
此示例最适合2-3个监视器。
随着框的扩展,闪烁方块的数量增加,并且开始缓慢闪烁得多,时钟开始跳数秒。
问题:
只需注释掉内部循环System.out调用:System.out.println(" Displaying " + numOfSquares + " squares within Inner Loop");
,并删除注释就可以修改外部环路System.out调用:System.out.println(" Displaying " + numOfSquares + " squares total");
。
这告诉我,即使归因于代码编写方式,EDT也无法处理工作量。如果出现这种情况,是否有可能使眨眼变得平滑,并使时钟不跳动?
将EDT中的frame.setTitle(timeFormat.format(currentTime) );
删除对于时钟来说效果很好,但是正方形仍然闪烁得更慢。
假设此示例满足应用程序要求,那么如何使正方形在大框架下闪烁(在小框架下闪烁)以及防止时钟跳秒呢?
您指出什么时候,应用程序只是在要求JVM和EDT做太多事情?
答案 0 :(得分:2)
您可以在其他线程上绘制,然后将要绘制的图像传递到组件中。这样,您可以将工作分流到其他线程,从而使EDT不再执行繁重的任务。您可以使用多个线程来准备所需的图像,这取决于您。我通常就是这样处理需要大量功率才能获得更好帧速率的图形的。
在您的示例中,我将创建一些带有多个线程的Exacutor,并创建一些Future来为您创建BufferedImage,然后为执行器提供许多这些任务,并在您准备好BufferedImage传递给它时到要绘制的组件。这样,您可以拥有更好的性能。执行器中有多少个线程,或者什么时候向执行器提供新任务,这些都留给OP进行考虑。