Java 如何使用GUI-使用paintcomponent()初始化GUI,然后基于鼠标添加GUI

Java 如何使用GUI-使用paintcomponent()初始化GUI,然后基于鼠标添加GUI,java,swing,user-interface,paintcomponent,Java,Swing,User Interface,Paintcomponent,标题说明一切。。。我的朋友和我正在这样做,我们不知道为什么Ball.java没有在gamePanel中制作球,然后制作GUI。顺便说一下,这是8球池。代码如下: 司机还是终结者 游戏面板 球 事情是这样的。你不希望一堆JPanels像球一样。您应该只使用一个JPanel进行绘制,并对所有球仅使用一个paintComponent方法。所以您的Ball类根本不需要扩展任何内容。Ball类应仅为保存数据的模型,如RGB颜色。您还应该在ball类中使用一个draw方法,该方法将Graphics对象作为参

标题说明一切。。。我的朋友和我正在这样做,我们不知道为什么Ball.java没有在gamePanel中制作球,然后制作GUI。顺便说一下,这是8球池。代码如下:

司机还是终结者 游戏面板 球
事情是这样的。你不希望一堆
JPanel
s像球一样。您应该只使用一个
JPanel
进行绘制,并对所有球仅使用一个
paintComponent
方法。所以您的
Ball
类根本不需要扩展任何内容。
Ball
类应仅为保存数据的模型,如RGB颜色。您还应该在ball类中使用一个draw方法,该方法将
Graphics
对象作为参数,并绘制球

public class Ball {
    int R, G, B;
    boolean striped;
    int x, y;

    public Ball(int R, int G, int B, boolean striped) {
        this.R = R:
        this.G = G;
        this.B = B;
        this.striped = striped;
    }

    public void drawBall(Graphics g) {
        if (isStriped) {
            // draw the ball with the values from this class
        }
        else {
            // draw the ball with the values from this class
        } 
    }
}
然后,在您正在使用的类中,您希望有一个
Ball
对象的列表

public class TablePanel extends JPanel {
    List<Ball> balls = new ArrayList<Ball>();

    public TablePanel(){
        makeBalls();
    }

    public void makeBalls(){
        balls.add(new Ball(213, 2, 255, true);
        // add more balls
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        for (Ball ball : balls) {
            ball.drawBall(g);
        }
    }
}


更新

MouseMotionListener
的示例。这是一个非常简单的例子。这根棍子不旋转也不动。看一看关于如何实现这一点的更复杂的细节

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class PoolStick extends JPanel{
    int x = 100;
    int y = 100;

    public PoolStick() {
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                Point p = e.getPoint();
                x = (int)p.getX();
                y = (int)p.getY();
                repaint();
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillRect(x, y, 5, 200);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 300);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                JFrame frame = new JFrame("Sorry Pool Table");
                frame.add(new PoolStick());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

事情是这样的。你不希望一堆
JPanel
s像球一样。您应该只使用一个
JPanel
进行绘制,并对所有球仅使用一个
paintComponent
方法。所以您的
Ball
类根本不需要扩展任何内容。
Ball
类应仅为保存数据的模型,如RGB颜色。您还应该在ball类中使用一个draw方法,该方法将
Graphics
对象作为参数,并绘制球

public class Ball {
    int R, G, B;
    boolean striped;
    int x, y;

    public Ball(int R, int G, int B, boolean striped) {
        this.R = R:
        this.G = G;
        this.B = B;
        this.striped = striped;
    }

    public void drawBall(Graphics g) {
        if (isStriped) {
            // draw the ball with the values from this class
        }
        else {
            // draw the ball with the values from this class
        } 
    }
}
然后,在您正在使用的类中,您希望有一个
Ball
对象的列表

public class TablePanel extends JPanel {
    List<Ball> balls = new ArrayList<Ball>();

    public TablePanel(){
        makeBalls();
    }

    public void makeBalls(){
        balls.add(new Ball(213, 2, 255, true);
        // add more balls
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        for (Ball ball : balls) {
            ball.drawBall(g);
        }
    }
}


更新

MouseMotionListener
的示例。这是一个非常简单的例子。这根棍子不旋转也不动。看一看关于如何实现这一点的更复杂的细节

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class PoolStick extends JPanel{
    int x = 100;
    int y = 100;

    public PoolStick() {
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                Point p = e.getPoint();
                x = (int)p.getX();
                y = (int)p.getY();
                repaint();
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillRect(x, y, 5, 200);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 300);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                JFrame frame = new JFrame("Sorry Pool Table");
                frame.add(new PoolStick());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

我认为你有两个问题:

  • 你不需要重写 对。这是一种受保护的方法,而不是公开的。如果你加上
    @重写此方法上的注释,然后编译器将
    抱怨。这是添加此注释的一个很好的理由
    每次需要重写某个方法时

  • Ball
    类从
    gamePanel
    扩展而来,因此当您在第一个类中调用
    super.paintComponent(g)
    时,它将在其祖先上调用
    paintComponent(g)
    。如果您在
    gamePanel
    中添加球,那么您将得到一个无休止的循环,这可能会导致堆栈溢出

  • 离题
    始终遵循。

    我认为您在这里有两个问题:

  • 你不需要重写 对。这是一种受保护的方法,而不是公开的。如果你加上
    @重写此方法上的注释,然后编译器将
    抱怨。这是添加此注释的一个很好的理由
    每次需要重写某个方法时

  • Ball
    类从
    gamePanel
    扩展而来,因此当您在第一个类中调用
    super.paintComponent(g)
    时,它将在其祖先上调用
    paintComponent(g)
    。如果您在
    gamePanel
    中添加球,那么您将得到一个无休止的循环,这可能会导致堆栈溢出

  • 离题
    始终遵循。

    太多代码了!你真的想让我们为你调试代码吗?请,至少,确保问题中的代码易于阅读。。。它的格式不好。请不要将代码格式与引用的文本混合使用。对代码、输入/输出和结构化文档(如HTML或XML)使用代码格式。为此,选择示例并单击消息发布/编辑表单上方的
    {}
    按钮。查看它现在看起来有多好?真是一团糟。我希望我已经说服了你,因为我不经常为人们这样做。该死的代码太多了!你真的想让我们为你调试代码吗?请,至少,确保问题中的代码易于阅读。。。它的格式不好。请不要将代码格式与引用的文本混合使用。对代码、输入/输出和结构化文档(如HTML或XML)使用代码格式。为此,选择示例并单击消息发布/编辑表单上方的
    {}
    按钮。查看它现在看起来有多好?真是一团糟。我希望我已经说服了你,因为我不经常为人们这样做。编译器不会抱怨
    public
    protected
    使用
    paintComponent
    。可以使用较高的可见性替代,但不能使用较低的可见性<代码>公共
    高于受保护的,因此没有problem@peeskillet注意!但在这种情况下,将
    paintComponent()
    公开并不好,是吗?编译器不会抱怨
    public
    受保护的
    。可以使用较高的可见性替代,但不能使用较低的可见性<代码>公共
    高于受保护的
    ,因此没有problem@peeskillet注意!但在这种情况下,将
    paintComponent()
    公之于众根本不好,是吗?好的,谢谢!另外,我如何制作一个矩形,沿着表示棒入池的自定义光标的线条跟随鼠标。我知道如何初始化GUI,但如何使每次移动鼠标时都有一个矩形跟随鼠标?您需要一个
    MouseMotionListener
    和@Override
    mouseMoved
    方法。使用
    e.getPoint()获取光标位置
    x`
    y
    cordinatesOk,谢谢!另外,我如何制作一个矩形,沿着表示棒入池的自定义光标的线条跟随鼠标。我知道如何初始化GUI,但如何使每次我将鼠标移动一个矩形f
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    
    public class PoolStick extends JPanel{
        int x = 100;
        int y = 100;
    
        public PoolStick() {
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    Point p = e.getPoint();
                    x = (int)p.getX();
                    y = (int)p.getY();
                    repaint();
                }
            });
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.fillRect(x, y, 5, 200);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 300);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable(){
                @Override
                public void run() {
                    JFrame frame = new JFrame("Sorry Pool Table");
                    frame.add(new PoolStick());
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }