简体   繁体   English

如何在JFrame中的JPanel中正确重绘

[英]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: 其他事宜:

  • Next I'm going to suggest that you not override paint but rather 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. 在您的方法中覆盖。
  • The easiest way to swap views is to use a CardLayout. 交换视图的最简单方法是使用CardLayout。
  • Better to use KeyBindings rather than a KeyListener as this will help you get around the KeyListener's focus issue, the issue which is probably preventing your KeyListener from working. 最好使用KeyBindings而不是KeyListener,因为这将帮助您解决KeyListener的焦点问题,该问题可能会阻止KeyListener正常工作。 It also allows you to use reusable Actions. 它还允许您使用可重复使用的操作。 Please search this site on KeyListeners to see what I mean and to see examples of Key Bindings (some by me). 请在KeyListeners上搜索此站点,以了解我的意思并查看键绑定的示例(某些示例由我执行)。 Also Google 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM