如何通过单击按钮在面板上绘制的对象周围移动

How to move around an object drawn on a panel with button click

我正在尝试在 Java 中构建弹跳游戏。我的项目有三个 classes,即 Main class,它创建了一个新的 window(frame),其中绘制了游戏按钮和弹跳对象。 GameInterface class 表示正在绘制的框架的属性,以及我创建的 RightPanel class 以便我可以覆盖 paint(Graphics) 方法来绘制我的弹跳物体。到目前为止,这就是我设法用代码绘制的内容。 您可以看到我有两个 JPanel,一个用于放置我的按钮,另一个用于接受在其上绘制圆球,即 RightPanel 我需要按钮事件侦听器的帮助来上下移动球,当用户按住按钮时,它需要继续向下移动直到达到向下顺序,向上按钮也是如此。 下面提供了我正在使用的代码。

游戏界面class

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

public class GameInterface extends JFrame {
    //we need this panel declaration in the class level for reference from other methods
    RightPanel rightpanel;
    //define the physical properties of the window
    public GameInterface(){
        setSize(new Dimension(600, 600));
        setResizable(false);
        setTitle("Bounce Game");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBackground(Color.black);
        //define a new JSplitPane and use it to add two JPanels
        JPanel leftpanel= new JPanel();
        //add buttons to the left panel programatically
        JButton up= new JButton("Move up");
        //set the event listeners for the buttons
        up.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //move my ball up
                //clear and redraw the ball while in a new position, use a timer or 
                 something

            }
        });
        JButton down = new JButton("Move down");
        down.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //move my ball down
                // rightpanel.getGraphics.fillColor(Color.RED);
                
            }
        });
        leftpanel.add(up);
        leftpanel.add(down);
        //add a new RightPanel with a drawn red object
        rightpanel= new RightPanel();
        JSplitPane splitpane= new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftpanel,rightpanel);
        this.add(splitpane);
        setVisible(true);
    }
}

右面板class

import javax.swing.*;
import java.awt.*;

public class RightPanel extends JPanel {
    //define the position where the circle will be drawn
    private int positionX=150;
    private int positionY=150;
    //I had an idea where we need a timer and then on delay we
    //decrement positionX by 3 for move down but can't figure out how to clear RightPanel
    private int radius=100;//as the shape is a circle
    //override the paint method to draw the bounce ball on the second panel

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.RED);
        g.fillOval(positionX,positionY,radius,radius);
    }
}

主要class

public class Main
{
    public static void main(String args[]){
        new GameInterface();
    }
}

如何向我的代码添加逻辑以使其上下移动圆圈,谢谢。 我尝试使用计时器对象清除面板,然后在球的新位置重新绘制球,但它绘制了一个垂直条,而不是清除原来绘制的球。

  1. 切勿在组件上调用 getGraphics()。
  2. 重写 paintComponent 而不是 paint
  3. 在覆盖中调用 super.paintComponent(g)。
  4. 提供 RightPanel class setter 方法,允许您更改绘图的 positionX 和 positionY 位置,
  5. 在按钮侦听器中,调用适当的 setter 方法,然后在更改位置后在 RightPanel 实例上调用 repaint()。

例如:

下面的关键代码位于更新位置值并调用重绘的 ActionListener 中:

moveRightBtn.addActionListener(e -> {
    // get and update the x position
    int x = drawOval.getPositionX();
    x += DELTA;

    // call the setter method
    drawOval.setPositionX(x);

    // request that Java repaint the JPanel
    drawOval.repaint();
});

并在绘图 JPanel 的 paintComponent 方法中调用 super 的方法并绘制椭圆:

@Override
protected void paintComponent(Graphics g) {
    // this is needed to do house-keeping painting, to clear "dirty" pixels
    super.paintComponent(g); 
    
    // this is needed to draw smooth graphics
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
    g2.setColor(OVAL_COLOR);
    g2.fillOval(positionX, positionY, RADIUS, RADIUS);
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;

@SuppressWarnings("serial")
public class MoveCircle extends JPanel {
    private static final int DELTA = 5;
    private DrawOval drawOval = new DrawOval();

    public MoveCircle() {
        JButton moveRightBtn = new JButton("Move Right");
        moveRightBtn.addActionListener(e -> {
            // get and update the x position
            int x = drawOval.getPositionX();
            x += DELTA;

            // call the setter method
            drawOval.setPositionX(x);

            // request that Java repaint the JPanel
            drawOval.repaint();
        });
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(moveRightBtn);

        setLayout(new BorderLayout());
        add(drawOval);
        add(buttonPanel, BorderLayout.LINE_START);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            MoveCircle mainPanel = new MoveCircle();

            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

}
@SuppressWarnings("serial")
class DrawOval extends JPanel {
    private static final int RADIUS = 100;
    private static final int PANEL_WIDTH = 600;
    private static final int PANEL_HEIGHT = 450;
    private static final Color OVAL_COLOR = Color.RED;
    private int positionX = 0;
    private int positionY = 0;
    
    public DrawOval() {
        setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
    }

    public int getPositionX() {
        return positionX;
    }

    public void setPositionX(int positionX) {
        this.positionX = positionX;
    }

    public int getPositionY() {
        return positionY;
    }

    public void setPositionY(int positionY) {
        this.positionY = positionY;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // this is needed to do house-keeping painting, to clear "dirty" pixels
        super.paintComponent(g); 
        
        // this is needed to draw smooth graphics
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        g2.setColor(OVAL_COLOR);
        g2.fillOval(positionX, positionY, RADIUS, RADIUS);
    }
}