Java中使用不同参数执行的调用操作

Java中使用不同参数执行的调用操作,java,swing,Java,Swing,由于我不熟悉Java图形(以及Java),所以我决定尝试编写一些示例。其中一个是太阳系,当我设法做到这一点时,我有一个问题——我不知道如何设定行星的速度,这样每个行星的速度都会不同。我尝试了不同的想法,在网上读了很多书,但现在我陷入了困境。代码如下: public class solarsystem { public static void main(String[] args) { System wnd = new System(); wnd.setDe

由于我不熟悉Java图形(以及Java),所以我决定尝试编写一些示例。其中一个是太阳系,当我设法做到这一点时,我有一个问题——我不知道如何设定行星的速度,这样每个行星的速度都会不同。我尝试了不同的想法,在网上读了很多书,但现在我陷入了困境。代码如下:

public class solarsystem {
    public static void main(String[] args) {
        System wnd = new System();
        wnd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        wnd.setSize(1000,1000);
        wnd.setVisible(true);
    }
}

class Planets extends JPanel implements ActionListener{
    int r = 70;
    int r2 = 5;
    int r3 = 10;
    int center_x, center_y;
    double angle;
    Timer timer;
    Planets(){
        super();
        timer = new Timer(100, this);
        timer.start();
        setBackground(new Color(0,0,0));
    }
    public void actionPerformed(ActionEvent e) {
        angle+=0.05;
        if(angle > (2*Math.PI))
            angle = 0.0;
        repaint();
    }
    public void DrawSun(int a, int b, int r, Graphics g) {
        g.fillOval(a, b, r, r);
    }
    public void DrawPlanet(int a, int b, int r, Graphics g) {
        g.fillOval(a, b, r, r);
    }
    public int moveXParam(double number) {
        int move_x = (int) (Math.cos(angle) * (getWidth()/number) + (getWidth()/2));
        return move_x;
    }
    public int moveYParam(double number) {
        int move_y = (int) (Math.sin(angle) * (getHeight()/ number) + (getHeight()/ 2));
        return move_y;
    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        center_x = getWidth()/2;
        center_y = getHeight()/2;
        Graphics2D g2d = (Graphics2D)g;
        //drawin Sun
        g2d.setColor(new Color(255,255,0));
        DrawSun(center_x-(r/2), center_y-(r/2), r, g);
        //Mercury
        g2d.setColor(new Color(255, 0, 0));
        DrawPlanet(moveXParam(9), moveYParam(9), r2, g);
        //Venus
        g2d.setColor(new Color(153, 76, 0));
        DrawPlanet(moveXParam(8), moveYParam(8), r3, g);
    }
}
class System extends JFrame{
    public System() {
        setContentPane(new Planets());
        setTitle("Solar System");
    }
}
问题是管理速度的代码部分是
angle+=0.05
actionPerformed
方法中,无论我如何尝试绕过它(使用开关盒、不同的方法等为每个行星输入不同的角度变化),我总是在同一个地方结束,必须将参数传递给actionPerformed,而我不能这样做。从我收集的信息来看,无论我做了什么更改,最终的角度更改都将被应用,因为
repaint()
。现在,这是我第一次使用
ActionListener
和任何类似的工具,所以我决定寻求帮助


那么,有没有办法改变角度+=0.05,比如水星的角度保持不变,而金星的角度是+=0.07?或者我应该完全抛弃
actionPerformed
,尝试实现不同的方法吗?非常感谢。(另外,正如我所说,我是新手,所以如果我在标题中犯了任何错误/代码中明显的错误/没有清楚地解释我的意思,请让我知道)

看来您对面向对象编程还是新手。你有很多不同的速度,角度,颜色等等,但是你试着用一个变量来处理它们。我在解决方案中所做的是创建一个新的
StellarObject
类,它保存所有这些变量。它还有一个
update()
方法和一个
draw()
方法,您可以调用该方法来更新所有物理相关变量,并分别将对象绘制到画布上。它们都存储在一个
列表中(如果知道对象的数量不会改变,还可以使用一个数组),然后迭代调用它们的方法

此外,虽然让
Planets
实现
ActionListener
并没有错,但这确实是一种不常见的方法。在编写面向对象的代码时,试着想想
Planets
是否真的在监听某个动作。你可以说物理上的滴答声是一种行为,但抽签事件和其他事情也可能是这样。通常,您会为每个要通知的操作创建单独的
ActionListener
s。我们正在使用lambda表示法,通过
新定时器(100,e->update())使一切变得更加紧凑。这在内部创建了一个新的
ActionListener
,它只调用
update()
方法。调用
StellarObject.forEach(StellarObject::update)时,我们也使用lambda表示法
,它将迭代所有
StellarObject
并调用它们的
update()
方法

public class Planets extends JPanel {
    private List<StellarObject> stellarObjects = new LinkedList<>();
    private Timer timer;
    private StellarObject sun = new StellarObject(0, 0, new Color(255, 255, 0), 70);
    private StellarObject mercury = new StellarObject(9, 0.07, new Color(255, 0, 0), 5);
    private StellarObject venus = new StellarObject(8, 0.05, new Color(153, 76, 0), 10);

    public Planets(){
        super();
        timer = new Timer(100, e -> update());
        timer.start();
        setBackground(Color.BLACK);
        Collections.addAll(stellarObjects, sun, mercury, venus);
    }

    public void update() {
        stellarObjects.forEach(StellarObject::update);
        repaint();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (StellarObject stellarObject : stellarObjects) {
            stellarObject.draw(g);
        }
    }

    public class StellarObject {
        private int distance;
        private double angle;
        private double angularVelocity;
        private Color color;
        private int radius;

        public StellarObject(int distance, double angularVelocity, Color color, int radius) {
            this.distance = distance;
            this.angularVelocity = angularVelocity;
            this.color = color;
            this.radius = radius;
        }

        public void draw(Graphics g) {
            g.setColor(color);
            g.fillOval(xDelta() - radius / 2, yDelta() - radius / 2, radius, radius);
        }

        private void update() {
            angle += angularVelocity;
            angle %= 2 * Math.PI;
        }

        public int xDelta() {
            return (int) ((distance == 0 ? 0 : Math.cos(angle) * (getWidth() / distance)) + (getWidth() / 2));
        }

        public int yDelta() {
            return (int) ((distance == 0 ? 0 : Math.sin(angle) * (getHeight() / distance)) + (getHeight() / 2));
        }
    }
}
公共类扩展JPanel{
private List stellarObjects=new LinkedList();
私人定时器;
私有StellarObject太阳=新StellarObject(0,0,新颜色(255,255,0),70);
私有StellarObject mercury=新StellarObject(9,0.07,新颜色(255,0,0),5);
私有恒星喷射器维纳斯=新恒星喷射器(8,0.05,新颜色(153,76,0),10);
公共行星(){
超级();
定时器=新定时器(100,e->update());
timer.start();
挫折背景(颜色:黑色);
收藏。addAll(恒星天体、太阳、水星、金星);
}
公共无效更新(){
forEach(StellarObject::update);
重新油漆();
}
公共组件(图形g){
超级组件(g);
用于(StellarObject StellarObject:stellarObjects){
stellarObject.draw(g);
}
}
公共类StellarObject{
私有整数距离;
私人双角度;
私人双角速度;
私人色彩;
私有整数半径;
公共星形对象(整数距离、双角度速度、颜色、整数半径){
这个距离=距离;
这个。角度速度=角度速度;
这个颜色=颜色;
这个半径=半径;
}
公共空间绘制(图g){
g、 设置颜色(颜色);
g、 圆角椭圆(xDelta()-radius/2,yDelta()-radius/2,radius,radius);
}
私有void更新(){
角度+=角速度;
角度%=2*Math.PI;
}
公共int-xDelta(){
返回(int)((距离==0?0:Math.cos(角度)*(getWidth()/distance))+(getWidth()/2));
}
公共int yDelta(){
返回(int)((距离==0?0:Math.sin(角度)*(getHeight()/distance))+(getHeight()/2));
}
}
}

如果您希望进一步提高java技能,您可能希望熟悉java特有的约定:始终将字段
设置为私有
,并且只允许通过getter和setter访问它们。所有方法名称都应该是camelCase(称之为
drawPlanet
,而不是
drawPlanet
)。类名应始终为CamelCase(称之为
SolarSystem
,而不是
SolarSystem
)。

将某种类型的增量值传递给
moveXParam
moveYParam
,这对于每个行星都是不同的,并且可以添加到
角度中。感谢您的详细解释!我会仔细检查并尝试改进我的代码。不过我只有一句话——当我试着运行你的代码时,我在
private List stellarObjects=new LinkedList()上出错
以及
stellarObjects
的以下所有用法。错误是
类型列表不是gener