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