如何在 java.awt.graphics 中停止闪烁?
Posted
技术标签:
【中文标题】如何在 java.awt.graphics 中停止闪烁?【英文标题】:How to stop flickering in java.awt.graphics? 【发布时间】:2018-12-23 10:20:29 【问题描述】:所以我开始学习 Java 并尝试使用 java.awt.graphics 创建一个基本的乒乓球游戏。 完成后,我看到它在游戏无法播放时闪烁很多。 这是我的主要课程,名为“pong”(多么有创意的名字)。
package pong;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class pong extends Applet implements Runnable,KeyListener
public static void main(String[] args)
public final int W=700,L=500;
p1 player1;
p1 player2;
ball b;
Thread thread;
public void init()
resize(W,L);
this.addKeyListener(this);
player2 = new p1(1);
b = new ball();
thread= new Thread(this);
player1 = new p1(2);
thread.start();
public void paint(Graphics g)
g.setColor(Color.BLACK);
g.fillRect(0,0,W,L);
if(!(b.getX()<-10 || b.getX()>690))
player1.draw(g);
b.draw(g);
player2.draw(g);
else if(b.getX()<-10)
g.setColor(Color.WHITE);
g.drawString("Right Player Won!",350,250);
else
g.setColor(Color.WHITE);
g.drawString("Left Player Won!",350,250);
@Override
public void update(Graphics g)
paint(g);
public void run()
for(;;)
player1.move();
player2.move();
b.move();
colitionchecker(1);
repaint();
try
Thread.sleep(17);
catch (InterruptedException e)
e.printStackTrace();
public void keyTyped(KeyEvent e)
public void keyPressed(KeyEvent e)
if(e.getKeyCode()==KeyEvent.VK_UP)
player1.setUp(true);
else if (e.getKeyCode()==KeyEvent.VK_DOWN)
player1.setDown(true);
else if(e.getKeyCode()==KeyEvent.VK_W)
player2.setUp(true);
else if(e.getKeyCode()==KeyEvent.VK_S)
player2.setDown(true);
public void keyReleased(KeyEvent e)
if(e.getKeyCode()==KeyEvent.VK_UP)
player1.setUp(false);
else if (e.getKeyCode()==KeyEvent.VK_DOWN)
player1.setDown(false);
else if(e.getKeyCode()==KeyEvent.VK_W)
player2.setUp(false);
else if(e.getKeyCode()==KeyEvent.VK_S)
player2.setDown(false);
public void colitionchecker(int num)
if(num == 1)
if(b.getX()<50 && b.getX()>20 && b.getY()>player2.getY() &&
b.getY()>=player2.getY()-80)
b.xv=-b.xv;
else
if(b.getX()<700 && b.getX()>660 && b.getY()>=player1.getY() && b.getY()<=player1.getY()+80)
b.xv=-b.xv;
package pong;
import java.awt.*;
public class p1 implements paddle
final double GRAVITY = 0.94;
double y=210,yv;
boolean up,down;
int player,x;
public p1(int player)
up=false; down=false;
if(player==1)
x=20;
else
x=660;
@Override
public void draw(Graphics g)
g.setColor(Color.WHITE);
g.fillRect(x, (int)y,20,80);
public void move()
if (up)
yv -= 2;
else if (down)
yv += 2;
else if (!down && !up)
yv *= GRAVITY;
if(yv>=15)
yv=5;
else if(yv<=-5)
yv=-5;
y += yv;
if(y<=0)
y=0;
else if(y>=420)
y=420;
public void setUp(boolean up)
this.up = up;
public void setDown(boolean down)
this.down = down;
public int getY()
return (int)y;
package pong;
import java.awt.*;
public class ball
double xv, yv, x, y;
public ball()
x = 350;
y = 250;
xv = 2;
yv = 1;
public int getY()
return (int)y;
public int getX()
return (int)x;
public void move()
x+=xv;
y+=yv;
if(y<10)
yv=-yv;
if(y>490)
yv=-yv;
public void draw(Graphics g)
g.setColor(Color.WHITE);
g.fillOval((int)x-10,(int)y-10,20,20);
package pong;
import java.awt.*;
public interface paddle
public void draw(Graphics g);
public int getY();
public void move();
我真的很迷茫,任何帮助都将不胜感激。 谢谢。
【问题讨论】:
“所以我开始学习 Java” - 所以你的第一课是,Applet 已经死了 - 最好把时间花在其他地方,使用基于 Swing 或 JavaFX windows 的 UI .Applet
不是双缓冲的,因此如果使用正确,Swing 和 JavaFX 都会出现闪烁。我也不鼓励您以这种方式使用Thread
,因为大多数 GUI 框架都不是线程安全的
另见Are Java applets worth learning?
忘记小程序、AWT 和 Swing。用于图形JavaFX 库。
【参考方案1】:
于是我开始学习Java
所以你的第一课是,Applets
已经死了 - 最好把时间花在其他地方,使用基于 Swing 或 JavaFX 窗口的 UI。
Applet
不是双缓冲的,因此如果使用正确,Swing 和 JavaFX 都会出现闪烁。
我也不鼓励您以这种方式使用Thread
,因为大多数 GUI 框架都不是线程安全的
我建议你看看:
Creating a GUI With JFC/Swing Getting Started with JavaFX作为基本出发点
基于 Swing 的解决方案
因为我可以很快做到……
KeyListener
是一个糟糕的选择,会困扰您,最好使用旨在克服其局限性的 Key Bindings API
您必须阅读的内容...
2D Graphics How to Use Key Bindings How to Use Swing Timers作为一个整体的基本示例
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test
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();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
);
public class TestPane extends JPanel
private DefaultPaddle player1;
private DefaultPaddle player2;
private Ball b;
public TestPane()
setBackground(Color.BLACK);
player1 = new DefaultPaddle(1);
player2 = new DefaultPaddle(2);
b = new Ball();
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "Player1.up.pressed", new UpAction(player1, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "Player1.up.released", new UpAction(player1, false));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "Player1.down.pressed", new DownAction(player1, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Player1.down.released", new DownAction(player1, false));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "Player2.up.pressed", new UpAction(player2, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "Player2.up.released", new UpAction(player2, false));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "Player2.down.pressed", new DownAction(player2, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), "Player2.down.released", new DownAction(player2, false));
Timer timer = new Timer(5, new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
player1.move();
player2.move();
b.move();
// colitionchecker(1);
repaint();
);
timer.start();
protected void addKeyBinding(KeyStroke ks, String name, Action action)
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(ks, name);
am.put(name, action);
public void colitionchecker(int num)
if (num == 1)
if (b.getX() < 50 && b.getX() > 20 && b.getY() > player2.getY()
&& b.getY() >= player2.getY() - 80)
b.xv = -b.xv;
else
if (b.getX() < 700 && b.getX() > 660 && b.getY() >= player1.getY() && b.getY() <= player1.getY() + 80)
b.xv = -b.xv;
@Override
public Dimension getPreferredSize()
return new Dimension(700, 500);
protected void paintComponent(Graphics g)
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
// if (!(b.getX() < -10 || b.getX() > 690))
player1.draw(g);
b.draw(g);
player2.draw(g);
// else if (b.getX() < -10)
// g.setColor(Color.WHITE);
// g.drawString("Right Player Won!", 350, 250);
// else
// g.setColor(Color.WHITE);
// g.drawString("Left Player Won!", 350, 250);
//
g2d.dispose();
public class UpAction extends AbstractAction
private DefaultPaddle paddle;
private boolean pressed;
public UpAction(DefaultPaddle paddle, boolean pressed)
this.paddle = paddle;
this.pressed = pressed;
@Override
public void actionPerformed(ActionEvent e)
System.out.println("Up " + pressed);
paddle.setUp(pressed);
public class DownAction extends AbstractAction
private DefaultPaddle paddle;
private boolean pressed;
public DownAction(DefaultPaddle paddle, boolean pressed)
this.paddle = paddle;
this.pressed = pressed;
@Override
public void actionPerformed(ActionEvent e)
paddle.setDown(pressed);
public interface Paddle
public void draw(Graphics g);
public int getY();
public void move();
public class DefaultPaddle implements Paddle
final double GRAVITY = 0.94;
double y = 210, yv;
boolean up, down;
int player, x;
public DefaultPaddle(int player)
up = false;
down = false;
if (player == 1)
x = 20;
else
x = 660;
@Override
public void draw(Graphics g)
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
public void move()
if (up)
yv -= 1;
else if (down)
yv += 1;
else if (!down && !up)
yv *= GRAVITY;
if (yv >= 15)
yv = 5;
else if (yv <= -5)
yv = -5;
y += yv;
if (y <= 0)
y = 0;
else if (y >= 420)
y = 420;
public void setUp(boolean up)
this.up = up;
public void setDown(boolean down)
this.down = down;
public int getY()
return (int) y;
public class Ball
double xv, yv, x, y;
public Ball()
x = 350;
y = 250;
xv = 2;
yv = 1;
public int getY()
return (int) y;
public int getX()
return (int) x;
public void move()
x += xv;
y += yv;
if (y < 10)
yv = -yv;
if (y > 490)
yv = -yv;
public void draw(Graphics g)
g.setColor(Color.WHITE);
g.fillOval((int) x - 10, (int) y - 10, 20, 20);
【讨论】:
以上是关于如何在 java.awt.graphics 中停止闪烁?的主要内容,如果未能解决你的问题,请参考以下文章