Java 小程序 paint() 方法闪烁
Java Applet paint() method flickering
我一直在 Java 进行细胞进化模拟。众所周知,我是一名 beginner/intermediate Java 程序员。我知道几乎所有的基础知识,然后是一点点,但我不太具备从头开始编写代码的技能。我这里的代码大致基于我在网上找到的资源,我添加了自己的风格以及我在网上找到的其他一些部分。它似乎工作得很好,除了屏幕闪烁。似乎每次调用 repaint() 时它都会闪烁,可能是清除和重绘。它创造了一些几乎不可能看到的东西。我的代码中没有错误。我刚开始使用小程序,所以如果有更好的方法,请告诉我。如何阻止屏幕闪烁?有没有一种简单的方法来缓冲图像以防止这种情况发生?下面是绘制小程序的class
/* <!-- Defines the applet element used by the appletviewer. -->
<applet code='CellLife.java' width='1920' height='1080'></applet> */
import java.applet.Applet;
import java.awt.Event;
import java.awt.Graphics;
import java.util.Enumeration;
import java.util.Vector;
public class CellLife extends Applet implements Runnable {
// ========================================================================
// VARIABLES
// ========================================================================
// Data
/** Thread object for CellLife applet */
private Thread m_cellLife = null;
// Static constants
/**
* the maximum number of creatures in the world. When the number of
* creatures alive drops below half this, a new one is created to bring the
* numbers back up.
*/
protected static final int MAX_CREATURES = 60;
// Data
/**
* A list of the creatures currently alive. Stores CLCreature references.
*/
protected Vector creatures;
/** The world is a rectangle from (0,0) to (limit.x,limit,y) */
protected CL2dVector limit;
/**
* The number of creatures that have been born since the simulation started
*/
protected long generations;
/** A test creature controllable by the user to allow response testing */
private CLCreature testCreature;
/** space-partitioning structure to speed collision detection */
protected CLBuckets buckets;
// ========================================================================
// METHODS
// ========================================================================
public CellLife() {
creatures = new Vector();
limit = new CL2dVector(500.0F, 500.0F);
generations = 0;
// initilaize our bucket structure
float bucketScale = CLCell.RADIUS; // could stretch to root-two times
// this
buckets = new CLBuckets(bucketScale, (int) Math.ceil(limit.x / bucketScale), (int) Math.ceil(limit.y / bucketScale));
}
public String getAppletInfo() {
return "Name: Cell Evolution\r\n" + "Author: Josh Marchand\r\n" + "Made in Eclipse";
}
// first time initialazion
public void init() {
resize((int) limit.x, (int) limit.y);
for (int i = 0; i < MAX_CREATURES; i++) {
CLCreature new_creature = new CLCreature();
new_creature.InitSimple(limit, buckets);
creatures.addElement(new_creature);
}
}
public void destroy() {
// TODO: Place applet cleanup code here
}
public void paint(Graphics g) {
g.drawString("No. creatures: " + creatures.size(), 0, 11);
g.drawString("Births: " + generations, 0, 22);
// draw cells
for (int i = 0; i < creatures.size(); i++) {
((CLCreature) creatures.elementAt(i)).Draw(g);
}
// DEBUG: also indicate the contents of the buckets
// buckets.Draw(g);
// get all creatures to do their stuff
CLCreature creature;
for (int i = 0; i < creatures.size(); i++) {
creature = (CLCreature) creatures.elementAt(i);
if (creature.DoTimeStep(g, buckets, limit) && creatures.size() < MAX_CREATURES) {
// inherit new creature from current
CLCreature newCreature = new CLCreature();
newCreature.InheritFrom(creature, buckets, limit);
creatures.addElement(newCreature);
generations++;
}
}
// delete the ones that died doing it
for (Enumeration e = creatures.elements(); e.hasMoreElements();) {
creature = (CLCreature) e.nextElement();
if (creature.hasDied) creatures.removeElement(creature);
}
// breed nwe creatures if pop. is low
if (creatures.size() < MAX_CREATURES / 2) {
// just add one for now,fix later
CLCreature newCreature = new CLCreature();
newCreature.InheritFrom((CLCreature) creatures.elementAt((int) Math.random() * creatures.size()), buckets, limit);
creatures.addElement(newCreature);
generations++;
}
}
public void start() {
if (m_cellLife == null) {
m_cellLife = new Thread(this);
m_cellLife.start();
}
// TODO: place any additional startup code here
}
public void stop() {
if (m_cellLife != null) {
m_cellLife.stop();
m_cellLife = null;
}
}
public void run() {
while (true) {
try {
repaint();
// quick nap here to allow user interface to catch up
Thread.sleep(100);
} catch (InterruptedException e) {
stop();
}
}
}
public boolean mouseDown(Event e, int x, int y) {
// create a single celled creature at specific loc
testCreature = new CLCreature();
testCreature.rootCell.location.x = x;
testCreature.rootCell.location.y = y;
testCreature.rootCell.type = CLGene.RED;
creatures.addElement(testCreature);
buckets.PutCell(testCreature.rootCell);
return true;
}
public boolean mouseDrag(Event e, int x, int y) {
testCreature.rootCell.location.x = x;
testCreature.rootCell.location.y = y;
return true;
}
public boolean mouseUp(Event evt, int x, int y) {
creatures.removeElement(testCreature);
buckets.RemoveCell(testCreature.rootCell);
return true;
}
}
非常感谢大家的帮助,我很抱歉我的"noobiness",我正在努力自学!
我会考虑使用称为双缓冲的技术,您可以在其中创建一个绑定到 Image 的离屏 Graphics 对象,在该对象上执行所有绘图,然后将结果绘制到屏幕上。
您可以找到有关从图像 here. More complete sample can be found here.
创建图形的便捷教程
我一直在 Java 进行细胞进化模拟。众所周知,我是一名 beginner/intermediate Java 程序员。我知道几乎所有的基础知识,然后是一点点,但我不太具备从头开始编写代码的技能。我这里的代码大致基于我在网上找到的资源,我添加了自己的风格以及我在网上找到的其他一些部分。它似乎工作得很好,除了屏幕闪烁。似乎每次调用 repaint() 时它都会闪烁,可能是清除和重绘。它创造了一些几乎不可能看到的东西。我的代码中没有错误。我刚开始使用小程序,所以如果有更好的方法,请告诉我。如何阻止屏幕闪烁?有没有一种简单的方法来缓冲图像以防止这种情况发生?下面是绘制小程序的class
/* <!-- Defines the applet element used by the appletviewer. -->
<applet code='CellLife.java' width='1920' height='1080'></applet> */
import java.applet.Applet;
import java.awt.Event;
import java.awt.Graphics;
import java.util.Enumeration;
import java.util.Vector;
public class CellLife extends Applet implements Runnable {
// ========================================================================
// VARIABLES
// ========================================================================
// Data
/** Thread object for CellLife applet */
private Thread m_cellLife = null;
// Static constants
/**
* the maximum number of creatures in the world. When the number of
* creatures alive drops below half this, a new one is created to bring the
* numbers back up.
*/
protected static final int MAX_CREATURES = 60;
// Data
/**
* A list of the creatures currently alive. Stores CLCreature references.
*/
protected Vector creatures;
/** The world is a rectangle from (0,0) to (limit.x,limit,y) */
protected CL2dVector limit;
/**
* The number of creatures that have been born since the simulation started
*/
protected long generations;
/** A test creature controllable by the user to allow response testing */
private CLCreature testCreature;
/** space-partitioning structure to speed collision detection */
protected CLBuckets buckets;
// ========================================================================
// METHODS
// ========================================================================
public CellLife() {
creatures = new Vector();
limit = new CL2dVector(500.0F, 500.0F);
generations = 0;
// initilaize our bucket structure
float bucketScale = CLCell.RADIUS; // could stretch to root-two times
// this
buckets = new CLBuckets(bucketScale, (int) Math.ceil(limit.x / bucketScale), (int) Math.ceil(limit.y / bucketScale));
}
public String getAppletInfo() {
return "Name: Cell Evolution\r\n" + "Author: Josh Marchand\r\n" + "Made in Eclipse";
}
// first time initialazion
public void init() {
resize((int) limit.x, (int) limit.y);
for (int i = 0; i < MAX_CREATURES; i++) {
CLCreature new_creature = new CLCreature();
new_creature.InitSimple(limit, buckets);
creatures.addElement(new_creature);
}
}
public void destroy() {
// TODO: Place applet cleanup code here
}
public void paint(Graphics g) {
g.drawString("No. creatures: " + creatures.size(), 0, 11);
g.drawString("Births: " + generations, 0, 22);
// draw cells
for (int i = 0; i < creatures.size(); i++) {
((CLCreature) creatures.elementAt(i)).Draw(g);
}
// DEBUG: also indicate the contents of the buckets
// buckets.Draw(g);
// get all creatures to do their stuff
CLCreature creature;
for (int i = 0; i < creatures.size(); i++) {
creature = (CLCreature) creatures.elementAt(i);
if (creature.DoTimeStep(g, buckets, limit) && creatures.size() < MAX_CREATURES) {
// inherit new creature from current
CLCreature newCreature = new CLCreature();
newCreature.InheritFrom(creature, buckets, limit);
creatures.addElement(newCreature);
generations++;
}
}
// delete the ones that died doing it
for (Enumeration e = creatures.elements(); e.hasMoreElements();) {
creature = (CLCreature) e.nextElement();
if (creature.hasDied) creatures.removeElement(creature);
}
// breed nwe creatures if pop. is low
if (creatures.size() < MAX_CREATURES / 2) {
// just add one for now,fix later
CLCreature newCreature = new CLCreature();
newCreature.InheritFrom((CLCreature) creatures.elementAt((int) Math.random() * creatures.size()), buckets, limit);
creatures.addElement(newCreature);
generations++;
}
}
public void start() {
if (m_cellLife == null) {
m_cellLife = new Thread(this);
m_cellLife.start();
}
// TODO: place any additional startup code here
}
public void stop() {
if (m_cellLife != null) {
m_cellLife.stop();
m_cellLife = null;
}
}
public void run() {
while (true) {
try {
repaint();
// quick nap here to allow user interface to catch up
Thread.sleep(100);
} catch (InterruptedException e) {
stop();
}
}
}
public boolean mouseDown(Event e, int x, int y) {
// create a single celled creature at specific loc
testCreature = new CLCreature();
testCreature.rootCell.location.x = x;
testCreature.rootCell.location.y = y;
testCreature.rootCell.type = CLGene.RED;
creatures.addElement(testCreature);
buckets.PutCell(testCreature.rootCell);
return true;
}
public boolean mouseDrag(Event e, int x, int y) {
testCreature.rootCell.location.x = x;
testCreature.rootCell.location.y = y;
return true;
}
public boolean mouseUp(Event evt, int x, int y) {
creatures.removeElement(testCreature);
buckets.RemoveCell(testCreature.rootCell);
return true;
}
}
非常感谢大家的帮助,我很抱歉我的"noobiness",我正在努力自学!
我会考虑使用称为双缓冲的技术,您可以在其中创建一个绑定到 Image 的离屏 Graphics 对象,在该对象上执行所有绘图,然后将结果绘制到屏幕上。 您可以找到有关从图像 here. More complete sample can be found here.
创建图形的便捷教程