简体   繁体   中英

Code crashes when making an object so repaint can be called from another class

I am currently doing a new project and long story short I am trying to implement action listener on a rectangle object so it can be moved up and down.

But here the code completely crashes when making an object of well in this case test2 class in the test3 class (yes I am aware of the need for a uppercase for classes). As I have replicated the problem making a new project and just used the code that is needed.

public class test {

    test2 board = new test2();

    public void frame() {
        JFrame b = new JFrame("test");
        b.setSize(905,705);
        b.setLocation(300,60);
        b.setResizable(false);
        b.setVisible(true);
        b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         
        b.add(board);
    }

    public static  void main(String[] args) {
        test start = new test();
        start.frame();
    }
}

public class test2 extends JPanel {

    public int playerScore = 0;
    public int opponentScore = 0;
    test3 player = new test3();
    
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        board(g);
        g.setColor(Color.WHITE);

        g2d.fill(player.player);
    }

    public void board(Graphics g) {
        g.setColor(Color.black);
        g.fillRect(0, 0, 900, 900);
    }
}

public class test3 {

    public boolean down = false;
    public boolean up = false;
    public int playerXpos = 45;
    public int playerYpos = 300;
    public int playerWidth = 15;
    public int playerHeight = 80;
    Rectangle player = new Rectangle(playerXpos, playerYpos, playerWidth, playerHeight);
    test2 theBoard = new test2();

    public void actionPerformed(ActionEvent e) {
        if (down) {
            down = true;

            if (up != true) {
                down = true;
            } else {
                up = true;
                down = false;
            }
        }
        
        if (up) {
            up = true;

            if (down != true) {
                up = true;
            } else {
                up = false;
                down = true;
            }
        }
    }

    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_UP) {
            for (int r = playerYpos; r >=0; r--) {
                if (r == 0) {
                    playerYpos = playerYpos - 20;
                } else {
                    playerYpos = playerYpos - 1;
                }
            
                if (playerYpos < 50) {
                    playerYpos = 50;
                }
            }

            theBoard.repaint();
        }

        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            for (int r = playerYpos; r >= 0; r--) {
                if (r == 0) {
                    playerYpos = playerYpos + 20;   
                } else {
                    playerYpos = playerYpos - 1;
                }
            
                if (playerYpos > 800){
                    playerYpos = 800;
                }
            }

            theBoard.repaint();
        }
    }

    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
    }
}

Your code doesn't compile.

I took some of your code and created the following GUI.

示例图形用户界面 1

Here's the GUI after moving the player rectangle.

示例图形用户界面 2

Oracle has a helpful tutorial, Creating a GUI With JFC/Swing . Skip the Netbeans section.

The first thing I did was start the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread .

I created a Player class to hold the player rectangle. This way, you can change the player shape in one place.

I created a JFrame . The JFrame methods have to be called in a specific order. This is the order I use for my Swing applications.

I created a drawing JPanel . This JPanel is similar to yours, except I override the paintComponent method. I pass an instance of Player to the drawing JPanel so the JPanel can draw the player rectangle.

I used key bindings instead of a key listener. This makes the keys functional whether the drawing JPanel is in focus or not. Key bindings also made it easy for me to add the WASD keys as well as the arrow keys.

Here's the complete runnable code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class ExampleGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ExampleGUI());
    }
    
    private final DrawingPanel drawingPanel;
    
    private final Player player;
    
    public ExampleGUI() {
        this.player = new Player();
        this.drawingPanel = new DrawingPanel(player);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Example GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(drawingPanel, BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        setKeyBindings(drawingPanel);
        frame.setVisible(true);
    }
    
    private void setKeyBindings(JPanel panel) {
        String up = "up";
        String down = "down";
        String left = "left";
        String right = "right";
        
        InputMap inputMap = panel.getInputMap();
        ActionMap actionMap = panel.getActionMap();
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), up);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), down);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), left);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), right);
        
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), up);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), down);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), left);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), right);
        
        actionMap.put(up, new PlayerAction(this, player, 0, -10));
        actionMap.put(down, new PlayerAction(this, player, 0, +10));
        actionMap.put(left, new PlayerAction(this, player, -10, 0));
        actionMap.put(right, new PlayerAction(this, player, +10, 0));
    }
    
    public void repaint() {
        drawingPanel.repaint();
    }
    
    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private final Player player;
        
        public DrawingPanel(Player player) {
            this.player = player;
            this.setPreferredSize(new Dimension(600, 600));
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            drawBoard(g2d);
            drawPlayer(g2d);
        }

        private void drawBoard(Graphics2D g2d) {
            g2d.setColor(Color.BLACK);
            g2d.fillRect(0, 0, getWidth(), getHeight());
        }

        private void drawPlayer(Graphics2D g2d) {
            g2d.setColor(player.getColor());
            g2d.fill(player.getPosition());
        }
        
    }
    
    public class PlayerAction extends AbstractAction {
        
        private static final long serialVersionUID = 1L;

        private final ExampleGUI frame;
        
        private final Player player;
        
        private final Point moveDirection;
        
        public PlayerAction(ExampleGUI frame, Player player, int x, int y) {
            this.frame = frame;
            this.player = player;
            this.moveDirection = new Point(x, y);
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            player.move(moveDirection);
            frame.repaint();
        }
        
    }
    
    public class Player {
        
        private final Color color;
        
        private Rectangle position;
        
        public Player() {
            this.color = Color.WHITE;
            this.position = new Rectangle(300, 300, 20, 80);
        }
        
        public void move(Point point) {
            position.x += point.x;
            position.y += point.y;
        }

        public Color getColor() {
            return color;
        }

        public Rectangle getPosition() {
            return position;
        }
        
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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