我试图制作俄罗斯方块游戏。但我的jframe GUI连续闪烁。但是,当我在代码中评论下面的行时,它不会闪烁。有人可以帮忙吗?
map.draw((Graphics2D) g);
JDK版本 - 1.8 NetBeans - 7.4
代码文件链接如下。
package GUI;
import Maps.MapGenerator;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.Timer;
public class BrickBreaker extends javax.swing.JFrame implements KeyListener, ActionListener {
private MapGenerator map;
public BrickBreaker() {
initComponents();
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
this.setTitle("Test Tetris");
//Map
map = new MapGenerator(3, 7);
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
time = new Timer(delay, this);
time.start();
}
public void paint(Graphics g) {
//background
g.setColor(Color.black);
g.fillRect(1, 1, 692, 592);
//map
map.draw((Graphics2D) g);
//score
g.setColor(Color.white);
g.setFont(new Font("serif", Font.BOLD, 25));
g.drawString("" + score, 560, 30);
//border
g.setColor(Color.yellow);
g.fillRect(0, 0, 3, 592);
g.fillRect(0, 0, 692, 3);
g.fillRect(691, 0, 3, 592);
//paddle
g.setColor(Color.green);
g.fillRect(playerPosX, 550, 100, 8);
//ball
g.setColor(Color.red);
g.fillOval(ballPosX, ballPosY, 20, 20);
g.dispose();
}
private boolean play = false;
private int score = 0;
private int totalBricks = 21;
private Timer time;
private int delay = 8;
private int playerPosX = 310;
private int ballPosX = 210;
private int ballPosY = 350;
private int ballXDir = -1;
private int ballYDir = -2;
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new java.awt.Dimension(700, 600));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 525, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 403, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(BrickBreaker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(BrickBreaker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(BrickBreaker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(BrickBreaker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new BrickBreaker().setVisible(true);
}
});
}
// Variables declaration - do not modify
// End of variables declaration
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
try {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
if (playerPosX >= 600) {
playerPosX = 600;
} else {
moveRight();
}
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
if (playerPosX < 10) {
playerPosX = 10;
} else {
moveLeft();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void moveRight() {
play = true;
playerPosX += 20;
}
public void moveLeft() {
play = true;
playerPosX -= 20;
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
time.start();
if (play) {
if (new Rectangle(ballPosX, ballPosY, 20, 20).intersects(new Rectangle(playerPosX, 550, 100, 8))) {
ballYDir = -ballYDir;
}
A:
for (int i = 0; i < map.map.length; i++) {
for (int j = 0; j < map.map[0].length; j++) {
if (map.map[i][j] > 0) {
int brickX = j * map.brickWidth + 60;
int brickY = i * map.brickHeight + 50;
int brickWidht = map.brickWidth;
int brickHeight = map.brickHeight;
Rectangle rect = new Rectangle(brickX, brickY, brickWidht, brickHeight);
Rectangle ballRect = new Rectangle(ballPosX, ballPosY, 20, 20);
Rectangle brickRect = rect;
if (ballRect.intersects(brickRect)) {
map.setBrickValue(0, i, j);
totalBricks--;
score += 2;
if (ballPosX + 19 <= brickRect.x || ballPosX + 1 >= brickRect.x + brickRect.width) {
ballXDir = -ballXDir;
} else {
ballYDir = -ballYDir;
}
break A;
}
}
}
}
ballPosX += ballXDir;
ballPosY += ballYDir;
if (ballPosX < 0) {
ballXDir = -ballXDir;
}
if (ballPosY < 0) {
ballYDir = -ballYDir;
}
if (ballPosX > 670) {
ballXDir = -ballXDir;
}
}
repaint();
}
}
地图生成器
package Maps;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class MapGenerator {
public int map[][];
public int brickWidth;
public int brickHeight;
public MapGenerator(int row, int col) {
map = new int[row][col];
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
map[i][j] = 1;
}
}
brickWidth = 240 / row;
brickHeight = 150 / col;
}
public void draw(Graphics2D g) {
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j] > 0) {
g.setColor(Color.black);
g.fillRect(j * brickWidth + 60, i * brickHeight + 50, brickWidth, brickHeight);
g.setStroke(new BasicStroke(3));
g.setColor(Color.white);
g.drawRect(j * brickWidth + 60, i * brickHeight + 50, brickWidth, brickHeight);
}
}
}
}
public void setBrickValue(int value, int row, int col) {
map[row][col] = value;
}
}
答案 0 :(得分:0)
顶级容器(如JFrame
)不是双缓冲的,这会导致闪烁。
这只是您不应该覆盖paint
顶级容器的众多原因之一。相反,从JPanel
开始并覆盖它paintComponent
,默认情况下,Swing组件会自动为您双重缓冲。
请查看Performing Custom Painting和Painting in AWT and Swing,了解有关绘画在Swing中如何运作的详细信息。
更合适的解决方案可能会开始看起来像这样......
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
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 boolean play = false;
private int score = 0;
private int totalBricks = 21;
private Timer timer;
private int delay = 8;
private int playerPosX = 310;
private int ballPosX = 210;
private int ballPosY = 350;
private int ballXDir = -1;
private int ballYDir = -2;
private MapGenerator map;
public TestPane() {
setBackground(Color.BLACK);
map = new MapGenerator(3, 7);
timer = new Timer(delay, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (play) {
if (new Rectangle(ballPosX, ballPosY, 20, 20).intersects(new Rectangle(playerPosX, 550, 100, 8))) {
ballYDir = -ballYDir;
}
for (int i = 0; i < map.map.length; i++) {
for (int j = 0; j < map.map[0].length; j++) {
if (map.map[i][j] > 0) {
int brickX = j * map.brickWidth + 60;
int brickY = i * map.brickHeight + 50;
int brickWidht = map.brickWidth;
int brickHeight = map.brickHeight;
Rectangle rect = new Rectangle(brickX, brickY, brickWidht, brickHeight);
Rectangle ballRect = new Rectangle(ballPosX, ballPosY, 20, 20);
Rectangle brickRect = rect;
if (ballRect.intersects(brickRect)) {
map.setBrickValue(0, i, j);
totalBricks--;
score += 2;
if (ballPosX + 19 <= brickRect.x || ballPosX + 1 >= brickRect.x + brickRect.width) {
ballXDir = -ballXDir;
} else {
ballYDir = -ballYDir;
}
}
}
}
}
ballPosX += ballXDir;
ballPosY += ballYDir;
if (ballPosX < 0) {
ballXDir = -ballXDir;
}
if (ballPosY < 0) {
ballYDir = -ballYDir;
}
if (ballPosX > 670) {
ballXDir = -ballXDir;
}
}
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(700, 600);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
//map
map.draw((Graphics2D) g);
//score
g.setColor(Color.white);
g.setFont(new Font("serif", Font.BOLD, 25));
g.drawString("" + score, 560, 30);
//border
g.setColor(Color.yellow);
g.fillRect(0, 0, 3, 592);
g.fillRect(0, 0, 692, 3);
g.fillRect(691, 0, 3, 592);
//paddle
g.setColor(Color.green);
g.fillRect(playerPosX, 550, 100, 8);
//ball
g.setColor(Color.red);
g.fillOval(ballPosX, ballPosY, 20, 20);
g2d.dispose();
}
}
public class MapGenerator {
public int map[][];
public int brickWidth;
public int brickHeight;
public MapGenerator(int row, int col) {
map = new int[row][col];
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
map[i][j] = 1;
}
}
brickWidth = 240 / row;
brickHeight = 150 / col;
}
public void draw(Graphics2D g) {
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j] > 0) {
g.setColor(Color.black);
g.fillRect(j * brickWidth + 60, i * brickHeight + 50, brickWidth, brickHeight);
g.setStroke(new BasicStroke(3));
g.setColor(Color.white);
g.drawRect(j * brickWidth + 60, i * brickHeight + 50, brickWidth, brickHeight);
}
}
}
}
public void setBrickValue(int value, int row, int col) {
map[row][col] = value;
}
}
}
此...
A:
for (int i = 0; i < map.map.length; i++) {
//...
//...
break A;
是糟糕设计的一个很好的迹象。不应该需要一个&#34; goto&#34;或&#34;标签&#34;基于良好的代码跳跃。
你必须想到你&#34;主循环&#34;在非常线性的操作集中,更新状态,检查冲突,更新UI。保持简单,保持快速
您还会发现the Key Bindings API将解决KeyListener