Applet即使使用Double Buffering后也会闪烁 [英] Applet Flickers even after using using Double Buffering
问题描述
我使用了双缓冲
的概念, strong>,但 Applet仍然闪烁!我提交的错误是什么?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Timer;
import javax.swing.JApplet;
public class Pong extends JApplet实现Runnable,MouseMotionListener {
Ball ball;
Paddle left_paddle;
桨右手
图像图像;
Graphics DoubleBuffered;
@Override
public void init(){
setSize(800,600);
addMouseMotionListener(this);
setFocusable(true);
requestFocusInWindow();
}
@Override
public void start(){
left_paddle = new Paddle(5,200,this);
right_paddle = new Paddle(this.getWidth() - 30,this.getHeight()/ 2,this);
ball = new Ball(100,100,left_paddle,right_paddle);
线程线程=新线程(this);
thread.start();
}
@Override
public void run(){
while(true){
ball.update(this);
repaint();
try {
Thread.sleep(17); //帧速率约为60 FPS
} catch(InterruptedException ex){
}
}
}
@Override
public void stop(){
}
@Override
public void destroy(){
}
@Override
public void update(Graphics g){
if(image == null){
image = createImage(this.getWidth(),this.getHeight());
DoubleBuffered = image.getGraphics();
}
DoubleBuffered.setColor(getBackground());
DoubleBuffered.fillRect(0,0,this.getWidth(),this.getHeight());
DoubleBuffered.setColor(getForeground());
paint(DoubleBuffered);
DoubleBuffered.drawImage(image,0,0,this);
}
@Override
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0,0,this.getWidth(),this.getHeight());
ball.paint(g);
left_paddle.paint(g);
right_paddle.paint(g);
g.setColor(Color.BLACK);
g.drawLine(this.getWidth()/ 2,0,this.getWidth()/ 2,this.getHeight());
}
@Override
public void mouseDragged(MouseEvent e){
}
@Override
public void mouseMoved MouseEvent e){
int y = e.getY();
int x = e.getX();
if(x< this.getWidth()/ 2){//控制左边的paddle
if(y< 0){
y = 0;
} else if(y + left_paddle.getHeight()> = this.getHeight()){
y = this.getHeight() - left_paddle.getHeight
}
left_paddle.mouse(y);
}
else {
if(y <0){
y = 0;
} else if(y + right_paddle.getHeight()> = this.getHeight()){
y = this.getHeight() - right_paddle.getHeight
}
right_paddle.mouse(y);
}
}
}
class Ball {
private int x;
private int y;
private float dx = 4;
private float dy = 5;
private int radius = 10;
private pad左,右;
Ball(int x,int y,Paddle x1,Paddle y1){
this.x = x;
this.y = y;
left = x1;
right = y1;
}
public void reset()
{
this.x = 400;
this.y = 200;
}
public void update(Pong ref)
{
if(x + dx< left.getX()+ left.getWidth()+ radius& amp; ;& y + dy + radius> = left.getY()& y + dy + radius< = left.getY()+ left.getHeight()){
x = left.getX )+ left.getWidth()+ radius;
dx * =(-1);
//检查左桨碰撞
}
else if(x + dx + radius> = right.getX()& y + dy + radius> = right。 getY()& y + dy + radius< = right.getY()+ right.getHeight()){
x = right.getX()
dx * =(-1);
//检查右侧桨碰撞
}
//如果球碰到边界在中点重置
else if(x + dx + radius> = ref.getWidth ()){
reset();
}
else if(x + dx reset();
}
else {
x + = dx;
}
if(y + dy + radius> ref.getHeight()){
y = ref.getHeight()
dy * =(-1);
}
else if(y + dy y = radius;
dy * =(-1);
}
else {
y + = dy;
}
}
public void paint(Graphics g)
{
g.setColor(Color.RED);
g.fillOval(x-radius,y-radius,2 * radius,2 * radius);
}
}
class Paddle {
private int x;
private int y;
private int width = 25;
private int height = 150;
private timer timer;
public Paddle(int x,int y,Pong ref){
this.x = x;
this.y = y;
}
public int getHeight(){
return height;
}
public int getWidth(){
return width;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void paint(Graphics g)
{
g.setColor(Color.BLUE);
g.fillRect(x,y,width,height);
}
//鼠标查找
void mouse(int y_final)
{
y = y_final;
}
}
你应该避免重写 paint
和更新
顶层容器的方法,例如 JApplet
。
您必须记住调用 super.update
,传递图形上下文您已创建。你还必须记得调用 super.paint
。这里有很多重要的功能,你不想跳过。
你也应该处置你创建的任何图形,因为他们倾向于hog memory;)
但是,由于你使用的是Swing组件,你应该创建一个自定义组件(从 JPanel
)并使用 paintComponent
方法。
这主要是因为Swing组件是默认的双缓冲...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.Timer;
import javax.swing.JApplet
import javax.swing.JPanel;
public class Pong extends JApplet {
private GamePane gamePane;
@Override
public void init(){
setSize(800,600);
gamePane = new GamePane();
setLayout(new BorderLayout());
add(gamePane);
}
@Override
public void start(){
gamePane.start();
}
@Override
public void stop(){
}
@Override
public void destroy
}
public class GamePane extends JPanel实现MouseMotionListener {
球球;
Paddle left_paddle;
桨右手
public GamePane(){
setBackground(Color.WHITE);
addMouseMotionListener(this);
setFocusable(true);
requestFocusInWindow();
}
public void start(){
left_paddle = new Paddle(5,200);
right_paddle = new Paddle(this.getWidth() - 30,this.getHeight()/ 2);
ball = new Ball(100,100,left_paddle,right_paddle);
timer timer = new Timer(40,new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
ball.update(GamePane.this);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g); //要更改生成方法的主体,请选择工具|模板。
ball.paint(g);
left_paddle.paint(g);
right_paddle.paint(g);
g.setColor(Color.BLACK);
g.drawLine(this.getWidth()/ 2,0,this.getWidth()/ 2,this.getHeight());
}
@Override
public void mouseDragged(MouseEvent e){
}
@Override
public void mouseMoved(MouseEvent e){
int y = e.getY();
int x = e.getX();
if(x< this.getWidth()/ 2){//控制左边的paddle
if(y< 0){
y = 0;
} else if(y + left_paddle.getHeight()> = this.getHeight()){
y = this.getHeight() - left_paddle.getHeight
}
left_paddle.mouse(y);
} else {
if(y <0){
y = 0;
} else if(y + right_paddle.getHeight()> = this.getHeight()){
y = this.getHeight() - right_paddle.getHeight
}
right_paddle.mouse(y);
}
}
}
class Ball {
private int x;
private int y;
private float dx = 4;
private float dy = 5;
private int radius = 10;
private pad左,右;
Ball(int x,int y,Paddle x1,Paddle y1){
this.x = x;
this.y = y;
left = x1;
right = y1;
}
public void reset(){
this.x = 400;
this.y = 200;
}
public void update(GamePane ref){
if(x + dx< left.getX()+ left.getWidth()+ radius& y + dy + radius> = left.getY()& y + dy + radius <= left.getY()+ left.getHeight()){
x = left.getX()+ left。 getWidth()+ radius;
dx * =(-1);
//检查左桨碰撞
} else if(x + dx + radius> = right.getX()& y + dy + radius> = right.getY()& ;& y + dy + radius< = right.getY()+ right.getHeight()){
x = right.getX()
dx * =(-1);
//检查正确的桨碰撞
} //如果球碰到边界在中间点重置
else if(x + dx + radius> = ref.getWidth()){
reset();
} else if(x + dx reset();
} else {
x + = dx;
}
if(y + dy + radius> ref.getHeight()){
y = ref.getHeight()
dy * =(-1);
} else if(y + dy y = radius;
dy * =(-1);
} else {
y + = dy;
}
}
public void paint(Graphics g){
g.setColor(Color.RED);
g.fillOval(x - radius,y - radius,2 * radius,2 * radius);
}
}
public class Paddle {
private int x;
private int y;
private int width = 25;
private int height = 150;
private timer timer;
public Paddle(int x,int y){
this.x = x;
this.y = y;
}
public int getHeight(){
return height;
}
public int getWidth(){
return width;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void paint(Graphics g){
g.setColor(Color.BLUE);
g.fillRect(x,y,width,height);
}
//鼠标查找
void mouse(int y_final){
y = y_final;
}
}
}
I am trying to make a 2 player Pong Applet where the user controls the paddle using mouse.
I have used the concept of Double Buffering, but the Applet still flickers !!! What is the mistake I am committing ?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Timer;
import javax.swing.JApplet;
public class Pong extends JApplet implements Runnable, MouseMotionListener {
Ball ball;
Paddle left_paddle;
Paddle right_paddle;
Image image;
Graphics DoubleBuffered;
@Override
public void init() {
setSize(800, 600);
addMouseMotionListener(this);
setFocusable(true);
requestFocusInWindow();
}
@Override
public void start() {
left_paddle = new Paddle(5, 200, this);
right_paddle = new Paddle(this.getWidth() - 30, this.getHeight() / 2, this);
ball = new Ball(100, 100, left_paddle, right_paddle);
Thread thread = new Thread(this);
thread.start();
}
@Override
public void run() {
while (true) {
ball.update(this);
repaint();
try {
Thread.sleep(17); //Frame rate of approx 60 FPS
} catch (InterruptedException ex) {
}
}
}
@Override
public void stop() {
}
@Override
public void destroy() {
}
@Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
DoubleBuffered = image.getGraphics();
}
DoubleBuffered.setColor(getBackground());
DoubleBuffered.fillRect(0, 0, this.getWidth(), this.getHeight());
DoubleBuffered.setColor(getForeground());
paint (DoubleBuffered);
DoubleBuffered.drawImage(image, 0, 0, this);
}
@Override
public void paint(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
ball.paint(g);
left_paddle.paint(g);
right_paddle.paint(g);
g.setColor(Color.BLACK);
g.drawLine(this.getWidth()/2, 0, this.getWidth()/2, this.getHeight());
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
int y = e.getY();
int x = e.getX();
if (x < this.getWidth()/2) { //Control the left paddle
if (y < 0) {
y = 0;
} else if (y + left_paddle.getHeight() >= this.getHeight()) {
y = this.getHeight() - left_paddle.getHeight();
}
left_paddle.mouse(y);
}
else {
if (y < 0) {
y = 0;
} else if (y + right_paddle.getHeight() >= this.getHeight()) {
y = this.getHeight() - right_paddle.getHeight();
}
right_paddle.mouse(y);
}
}
}
class Ball {
private int x;
private int y;
private float dx=4;
private float dy=5;
private int radius = 10;
private Paddle left, right;
Ball(int x, int y, Paddle x1, Paddle y1) {
this.x = x;
this.y = y;
left = x1;
right = y1;
}
public void reset ()
{
this.x = 400;
this.y = 200;
}
public void update(Pong ref)
{
if (x+dx < left.getX()+left.getWidth()+radius && y+dy+radius >= left.getY() && y+dy+radius <= left.getY()+left.getHeight()) {
x = left.getX()+left.getWidth()+radius;
dx *= (-1);
// checks the left paddle collision
}
else if (x+dx+radius >= right.getX() && y+dy+radius >= right.getY() && y+dy+radius <= right.getY()+right.getHeight() ) {
x = right.getX() - radius;
dx *= (-1);
//checks the right paddle collision
}
//if ball touches the boundary reset it at middle point
else if (x+dx+radius >= ref.getWidth()) {
reset();
}
else if (x + dx < radius) {
reset();
}
else {
x += dx;
}
if (y+dy +radius > ref.getHeight()) {
y = ref.getHeight() - radius - 1;
dy *= (-1);
}
else if (y + dy < radius) {
y = radius;
dy *= (-1);
}
else {
y += dy;
}
}
public void paint (Graphics g)
{
g.setColor(Color.RED);
g.fillOval(x-radius, y-radius, 2*radius, 2*radius);
}
}
class Paddle {
private int x;
private int y;
private int width = 25;
private int height = 150;
private Timer timer;
public Paddle(int x, int y, Pong ref) {
this.x = x;
this.y = y;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void paint (Graphics g)
{
g.setColor(Color.BLUE);
g.fillRect(x, y, width, height);
}
//mouse lookup
void mouse(int y_final)
{
y = y_final;
}
}
Generally speaking, you should avoid overriding the paint
and update
methods of top level containers like JApplet
.
You must remember to call super.update
, passing it the graphics context which you have created. You must also remember to call super.paint
. There is a lot of important functionality going in here that you don't want to skip over.
You should also be disposing of any graphics you create, as they tend to hog memory ;)
But, seen as you're using Swing components anyway, you should create yourself a custom component (from something like JPanel
) and use it's paintComponent
method.
The main reason for this is, Swing components are double buffered by default...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.Timer;
import javax.swing.JApplet;
import javax.swing.JPanel;
public class Pong extends JApplet {
private GamePane gamePane;
@Override
public void init() {
setSize(800, 600);
gamePane = new GamePane();
setLayout(new BorderLayout());
add(gamePane);
}
@Override
public void start() {
gamePane.start();
}
@Override
public void stop() {
}
@Override
public void destroy() {
}
public class GamePane extends JPanel implements MouseMotionListener {
Ball ball;
Paddle left_paddle;
Paddle right_paddle;
public GamePane() {
setBackground(Color.WHITE);
addMouseMotionListener(this);
setFocusable(true);
requestFocusInWindow();
}
public void start() {
left_paddle = new Paddle(5, 200);
right_paddle = new Paddle(this.getWidth() - 30, this.getHeight() / 2);
ball = new Ball(100, 100, left_paddle, right_paddle);
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ball.update(GamePane.this);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
ball.paint(g);
left_paddle.paint(g);
right_paddle.paint(g);
g.setColor(Color.BLACK);
g.drawLine(this.getWidth() / 2, 0, this.getWidth() / 2, this.getHeight());
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
int y = e.getY();
int x = e.getX();
if (x < this.getWidth() / 2) { //Control the left paddle
if (y < 0) {
y = 0;
} else if (y + left_paddle.getHeight() >= this.getHeight()) {
y = this.getHeight() - left_paddle.getHeight();
}
left_paddle.mouse(y);
} else {
if (y < 0) {
y = 0;
} else if (y + right_paddle.getHeight() >= this.getHeight()) {
y = this.getHeight() - right_paddle.getHeight();
}
right_paddle.mouse(y);
}
}
}
class Ball {
private int x;
private int y;
private float dx = 4;
private float dy = 5;
private int radius = 10;
private Paddle left, right;
Ball(int x, int y, Paddle x1, Paddle y1) {
this.x = x;
this.y = y;
left = x1;
right = y1;
}
public void reset() {
this.x = 400;
this.y = 200;
}
public void update(GamePane ref) {
if (x + dx < left.getX() + left.getWidth() + radius && y + dy + radius >= left.getY() && y + dy + radius <= left.getY() + left.getHeight()) {
x = left.getX() + left.getWidth() + radius;
dx *= (-1);
// checks the left paddle collision
} else if (x + dx + radius >= right.getX() && y + dy + radius >= right.getY() && y + dy + radius <= right.getY() + right.getHeight()) {
x = right.getX() - radius;
dx *= (-1);
//checks the right paddle collision
} //if ball touches the boundary reset it at middle point
else if (x + dx + radius >= ref.getWidth()) {
reset();
} else if (x + dx < radius) {
reset();
} else {
x += dx;
}
if (y + dy + radius > ref.getHeight()) {
y = ref.getHeight() - radius - 1;
dy *= (-1);
} else if (y + dy < radius) {
y = radius;
dy *= (-1);
} else {
y += dy;
}
}
public void paint(Graphics g) {
g.setColor(Color.RED);
g.fillOval(x - radius, y - radius, 2 * radius, 2 * radius);
}
}
public class Paddle {
private int x;
private int y;
private int width = 25;
private int height = 150;
private Timer timer;
public Paddle(int x, int y) {
this.x = x;
this.y = y;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void paint(Graphics g) {
g.setColor(Color.BLUE);
g.fillRect(x, y, width, height);
}
//mouse lookup
void mouse(int y_final) {
y = y_final;
}
}
}
这篇关于Applet即使使用Double Buffering后也会闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!