[英]How to repaint properly in JPanel inside JFrame
stackoverflow community! stackoverflow社区! I am making a small GUI based game in JAVA. 我正在用JAVA制作基于GUI的小型游戏。 I am having a few troubles right now. 我现在有一些麻烦。 To give you basic understanding of my program, 为了让您对我的程序有基本的了解,
I have a window that shows menu(JPanel) first. 我有一个窗口,首先显示菜单(JPanel)。 When I click on "start game" button. 当我点击“开始游戏”按钮时。 It proceeds to another JPanel on which I can play game. 它进入另一个我可以玩游戏的JPanel。 ![menu_window][1] ![menu_window] [1]
I have a timer working on a small bullet that is moving periodically. 我有一个计时器在处理定期移动的小子弹。 Every time the timer works, the Panel repaints the bullet. 每次计时器工作时,面板都会重新绘制项目符号。 I can see the repaint method works but it doesn't remove the previous trace. 我可以看到repaint方法有效,但是它不会删除以前的跟踪。
![enter image description here][2] ![在此处输入图片描述] [2]
This is my main class 这是我的主班
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main {
private final int window_x_size = 500;
private final int window_y_size = 500;
private JFrame frame;
private JPanel Menu;
private Game myGame = new Game();//extends from JPanel
private JButton startButton = new JButton("Game Start");
private JButton exitButton = new JButton("Game Exit");
private JButton showRank = new JButton("Rank");
private JButton OneOnOne = new JButton("One on One");
private ActionListener MyButtonListener = new MyButtonListener();
public class MyButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == startButton) {
frame.remove(Menu);
frame.setContentPane(myGame);
frame.validate();
frame.repaint(); // prefer to write this always.
} else if (source == exitButton) {
System.exit(1);
} else if (source == showRank) {
} else {// one on one
}
}
}
public Main() {
frame = new JFrame();
frame.setBackground(Color.white);
frame.setSize(window_x_size, window_y_size);
frame.setTitle("My First GUI Game");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
Menu = new JPanel();
startButton.addActionListener(MyButtonListener);
exitButton.addActionListener(MyButtonListener);
showRank.addActionListener(MyButtonListener);
OneOnOne.addActionListener(MyButtonListener);
Menu.setLayout(new GridLayout(4, 1));
Menu.add(startButton);
Menu.add(OneOnOne);
Menu.add(showRank);
Menu.add(exitButton);
frame.setContentPane(Menu);
frame.setVisible(true);
}
public static void main(String[] args) {
/*
* This is the most important part of your GUI app, never forget
* to schedule a job for your event dispatcher thread :
* by calling the function, method or constructor, responsible
* for creating and displaying your GUI.
*/
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new Main();
}
});
}
}
This is my Game class 这是我的游戏课
import java.awt.Graphics;
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 java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Game extends JPanel {
private Random rnd = new Random();
private ActionListener MyBulletListener = new BulletListener();
public KeyListener myKeyListen = new MyKeyListener();
Timer bullet_timer;
private boolean IsExplosion = false;
private ImageIcon spacecraftImg = new ImageIcon("spacecraft.png");
private Rectangle spacecraftBox = new Rectangle(5, 10,
spacecraftImg.getIconWidth(), spacecraftImg.getIconHeight());
private ImageIcon explosionImg = new ImageIcon("explosion.png");
private ImageIcon bulletImg = new ImageIcon("bullet.png");
private Rectangle bulletBox = new Rectangle(70, 200,
bulletImg.getIconWidth(), bulletImg.getIconHeight());
private MySound explosion_sound = new MySound();
public Game() {
addKeyListener(myKeyListen);
bullet_timer = new Timer(500, MyBulletListener);
bullet_timer.start();
}
public class MyKeyListener implements KeyListener {
private int x;
private int y;
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();
if (keyCode == 37) {
x = -10;
y = 0;
} else if (keyCode == 38) {
x = 0;
y = -10;
} else if (keyCode == 39) {
x = 10;
y = 0;
} else {
x = 0;
y = 10;
}
if (spacecraftBox.x + x < 0
|| spacecraftBox.x + x > 500
|| spacecraftBox.y + y < 0
|| spacecraftBox.y + y > 500) {
} else {
move_plane(x, y);
repaint();
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public class BulletListener implements ActionListener {
private int x;
private int y;
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Object source = e.getSource();
if (source == bullet_timer) {
int dir = rnd.nextInt(4);
if (dir == 0) {// move left
x = -10;
y = 0;
} else if (dir == 1) {// move right
x = 10;
y = 0;
} else if (dir == 2) {// move up
x = 0;
y = -10;
} else {// move down
x = 0;
y = 10;
}
if (bulletBox.x + x < 0
|| bulletBox.x + x > 500
|| bulletBox.y + y < 0
|| bulletBox.y + y > 500) {
} else {
move_bullets(x, y);
repaint();
}
}
}
}
@Override
public void paint(Graphics g) {
g.drawImage(bulletImg.getImage(), (int) bulletBox.getX(),
(int) bulletBox.getY(), null);
g.drawImage(spacecraftImg.getImage(), (int) spacecraftBox.getX(),
(int) spacecraftBox.getY(), null);
if (IsExplosion) {
g.drawImage(explosionImg.getImage(), (int) bulletBox.getX(),
(int) bulletBox.getY(), null);
MySound.play();
IsExplosion = false;
}
}
public void move_plane(int x, int y) {
spacecraftBox.translate(x, y);
if (spacecraftBox.intersects(bulletBox)) {
IsExplosion = true;
}
}
public void move_bullets(int x, int y) {
bulletBox.translate(x, y);
if (spacecraftBox.intersects(bulletBox)) {
IsExplosion = true;
}
}
}
Plus I added KeyListener but it doesn't work. 另外,我添加了KeyListener,但是它不起作用。 I have no idea how to fix it out. 我不知道如何解决它。
I tried googling about the issue. 我尝试使用Google搜索该问题。 I tried the game panel focusable in main class but it didn't work. 我尝试了以主要班级为重点的游戏面板,但是没有用。
I would really appreciate your help. 我将衷心感谢您的帮助。
Best Regards, 最好的祝福,
Dongseop Dongseop
This is almost always due to your painting method not calling the super's painting method to clean up dirty pixels. 这几乎总是由于您的绘画方法未调用super的绘画方法来清除脏像素而引起的。 Since you're overriding paint, you would need to call super.paint(g);
由于您要覆盖绘画,因此需要调用super.paint(g);
as the first method call in your paint override. 作为绘画替代中的第一个方法调用。
Other issues: 其他事宜:
paintComponent(Graphics g)
, as this will give your animation automatic double buffering and make the animation smoother. 接下来,我建议您不要覆盖paint,而要覆盖paintComponent(Graphics g)
,因为这将使您的动画具有自动双重缓冲,并使动画更加平滑。 Again, call super.paintComponent(g);
再次,调用super.paintComponent(g);
in your method override. 在您的方法中覆盖。 Java Key Bindings Tutorial
to see the official tutorial on how to use these. 另外,请参阅Google Java Key Bindings Tutorial
以了解有关如何使用它们的官方教程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.