Java(Swing) - 如何旋转一堆线?

时间:2023-02-04 17:19:43

I've been looking for this online, but I can't seem to find how to rotate a bunch of lines. I made a "plane" with the Graphics.drawLine() function, but I want to know how to rotate the whole thing 90 degrees to the right when it hits a wall. Here is my current code:

我一直在网上寻找这个,但我似乎无法找到如何旋转一堆线。我使用Graphics.drawLine()函数创建了一个“平面”,但我想知道如何将整个东西旋转到墙壁时向右旋转90度。这是我目前的代码:

/* MovePlane
 * Moves plane to the right, down, left, up, and repeats using Timer object
 */

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


public class MovePlane extends JPanel implements ActionListener {
   private int delay = 5;
   private Timer timer;

   private int x = 10;      // x position
   private int y = 10;      // y position

   private boolean right = true;
   private boolean up = true;

   public MovePlane() {
       timer = new Timer(delay, this);
       timer.start();       // start the timer - infinite
   }

   public void actionPerformed(ActionEvent e) {
    // will run when the timer fires
       repaint();
   }

   public void paintComponent(Graphics g) {
       // both paint and paintComponent work - difference?
       super.paintComponent(g);    // call superclass's paintComponent 
       g.drawLine(x,y,x+20,y);               // body - drawn in terms of x
       g.drawLine(x+15,y-5,x+15,y+5);    // wing
       g.drawLine(x,y-2,x,y+2);  
       if (right && up) {
            x++;
            if (x == getWidth()-25) {
                right = false;
                up = false;
            }
       } else if (!right && !up) {
            y++;
            if (y == getHeight()-10) {
                up = true;
            }
       } else {
            if (x <= getWidth()-15 && x > 0) {
                x--;
            }
            if (x == 0) {
                y--;
            }
            if (y == 10) {
                right = true;
            }
       }
    }

    public static void main(String args[]) {
        JFrame frame = new JFrame("Move Plane");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MovePlane bp = new MovePlane(); 
        frame.add(bp);
        frame.setSize(300, 300); // set frame size
        frame.setVisible(true); // display frame
    }

}

1 个解决方案

#1


2  

You need to change it everytime you change the direction, so, you need to move your g.drawLine(...) calls inside each if conditions...

每次更改方向时都需要更改它,因此,如果条件允许,则需要在每个内部移动g.drawLine(...)调用...

But while rotating the plane, you also need to take care of the "bounds" or the limits of the screen, so, I modified if (x == 0) and ... && x > 0 conditions to have a gap of 20 instead...

但是在旋转飞机时,你还需要注意屏幕的“边界”或限制,所以,我修改了if(x == 0)和... && x> 0条件,以便有20的间隙代替...

Let's start for the plane going from left to right:

让我们从左到右开始飞机:

g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
g.drawLine(x + 15, y - 5, x + 15, y + 5);    // wing
g.drawLine(x, y - 2, x, y + 2);

This is telling us that:

这告诉我们:

  • Your plane's body length is 20
  • 你飞机的体长是20

  • Your wings are 15 units from the back
  • 你的翅膀距离背部15个单位

  • Your tail is right on the back
  • 你的尾巴就在后面

So, to change it to move from left to right, we need to invert the wings and tail positions...

因此,要改变它从左向右移动,我们需要反转机翼和尾部位置......

  • Plane lenght is still the same
  • 飞机长度仍然相同

  • Wings are now 5 units from the back
  • 翅膀现在从后面5个单位

  • Tail is now on the front
  • 尾巴现在在前面

Then, we have this code:

然后,我们有这个代码:

g.drawLine(x, y, x + 20, y);               // Body length 20
g.drawLine(x + 5, y - 5, x + 5, y + 5);    // Wing's are 5 units from the front
g.drawLine(x + 20, y - 2, x + 20, y + 2);  // Tail is on the front (at body's length)

And for when going down:

下降的时候:

  • Body's length is now on Y axis
  • 身体长度现在在Y轴上

  • Wings should be at 15 units from the back
  • 翅膀应该从后面15个单位

  • Tail is at the back
  • 尾巴在后面

So we have:

所以我们有:

g.drawLine(x, y, x, y + 20);               // Body is now on Y axis
g.drawLine(x - 5, y + 15, x + 5, y + 15);    // Wings are 15 units from the back
g.drawLine(x - 2, y, x + 2, y); // Tail is on the back

And applying same logic as when going from right to left:

并应用与从右到左相同的逻辑:

g.drawLine(x, y + 20, x, y);
g.drawLine(x - 5, y + 5, x + 5, y + 5);
g.drawLine(x - 2, y + 20, x + 2, y + 20);

Then your paintComponent(...) method looks like this:

然后你的paintComponent(...)方法如下所示:

public void paintComponent(Graphics g) {
    // both paint and paintComponent work - difference?
    super.paintComponent(g);    // call superclass's paintComponent
    if (right && up) {
        g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
        g.drawLine(x + 15, y - 5, x + 15, y + 5);    // wing
        g.drawLine(x, y - 2, x, y + 2);
        x++;
        if (x == getWidth() - 25) {
            right = false;
            up = false;
        }
    } else if (!right && !up) {
        g.drawLine(x, y, x, y + 20);               // body - drawn in terms of x
        g.drawLine(x - 5, y + 15, x + 5, y + 15);    // wing
        g.drawLine(x - 2, y, x + 2, y);
        y++;
        if (y == getHeight() - 25) {
            up = true;
        }
    } else {
        if (x <= getWidth() - 15 && x > 20) {
            g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
            g.drawLine(x + 5, y - 5, x + 5, y + 5);    // wing
            g.drawLine(x + 20, y - 2, x + 20, y + 2);
            x--;
        }
        if (x == 20) {
            g.drawLine(x, y, x, y + 20);               // body - drawn in terms of x
            g.drawLine(x - 5, y + 5, x + 5, y + 5);    // wing
            g.drawLine(x - 2, y + 20, x + 2, y + 20);
            y--;
        }
        if (y == 10) {
            right = true;
        }
    }
}

And that's it! Here's an image showing how it looks like:

就是这样!这是一个显示它的样子的图像:

Java(Swing) - 如何旋转一堆线?

Additional tips:

  1. Don't call frame.setSize() but override MovePlane's JPanel getPreferredSize() to return a fixed size of 300, 300.

    不要调用frame.setSize(),而是覆盖MovePlane的JPanel getPreferredSize()以返回固定大小300,300。

  2. Always place your GUI in the Event Dispatch Thread (EDT) by wrapping your main method like this:

    始终将GUI放在事件调度线程(EDT)中,方法是将主方法包装为:

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Your code here
            }
        });
    }
    
  3. Related to tip #1, call frame.pack(); instead of frame.setSize() after overriding JPanel's getPreferredSize() :)

    与提示#1相关,请调用frame.pack();覆盖JPanel的getPreferredSize()后,而不是frame.setSize():)

#1


2  

You need to change it everytime you change the direction, so, you need to move your g.drawLine(...) calls inside each if conditions...

每次更改方向时都需要更改它,因此,如果条件允许,则需要在每个内部移动g.drawLine(...)调用...

But while rotating the plane, you also need to take care of the "bounds" or the limits of the screen, so, I modified if (x == 0) and ... && x > 0 conditions to have a gap of 20 instead...

但是在旋转飞机时,你还需要注意屏幕的“边界”或限制,所以,我修改了if(x == 0)和... && x> 0条件,以便有20的间隙代替...

Let's start for the plane going from left to right:

让我们从左到右开始飞机:

g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
g.drawLine(x + 15, y - 5, x + 15, y + 5);    // wing
g.drawLine(x, y - 2, x, y + 2);

This is telling us that:

这告诉我们:

  • Your plane's body length is 20
  • 你飞机的体长是20

  • Your wings are 15 units from the back
  • 你的翅膀距离背部15个单位

  • Your tail is right on the back
  • 你的尾巴就在后面

So, to change it to move from left to right, we need to invert the wings and tail positions...

因此,要改变它从左向右移动,我们需要反转机翼和尾部位置......

  • Plane lenght is still the same
  • 飞机长度仍然相同

  • Wings are now 5 units from the back
  • 翅膀现在从后面5个单位

  • Tail is now on the front
  • 尾巴现在在前面

Then, we have this code:

然后,我们有这个代码:

g.drawLine(x, y, x + 20, y);               // Body length 20
g.drawLine(x + 5, y - 5, x + 5, y + 5);    // Wing's are 5 units from the front
g.drawLine(x + 20, y - 2, x + 20, y + 2);  // Tail is on the front (at body's length)

And for when going down:

下降的时候:

  • Body's length is now on Y axis
  • 身体长度现在在Y轴上

  • Wings should be at 15 units from the back
  • 翅膀应该从后面15个单位

  • Tail is at the back
  • 尾巴在后面

So we have:

所以我们有:

g.drawLine(x, y, x, y + 20);               // Body is now on Y axis
g.drawLine(x - 5, y + 15, x + 5, y + 15);    // Wings are 15 units from the back
g.drawLine(x - 2, y, x + 2, y); // Tail is on the back

And applying same logic as when going from right to left:

并应用与从右到左相同的逻辑:

g.drawLine(x, y + 20, x, y);
g.drawLine(x - 5, y + 5, x + 5, y + 5);
g.drawLine(x - 2, y + 20, x + 2, y + 20);

Then your paintComponent(...) method looks like this:

然后你的paintComponent(...)方法如下所示:

public void paintComponent(Graphics g) {
    // both paint and paintComponent work - difference?
    super.paintComponent(g);    // call superclass's paintComponent
    if (right && up) {
        g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
        g.drawLine(x + 15, y - 5, x + 15, y + 5);    // wing
        g.drawLine(x, y - 2, x, y + 2);
        x++;
        if (x == getWidth() - 25) {
            right = false;
            up = false;
        }
    } else if (!right && !up) {
        g.drawLine(x, y, x, y + 20);               // body - drawn in terms of x
        g.drawLine(x - 5, y + 15, x + 5, y + 15);    // wing
        g.drawLine(x - 2, y, x + 2, y);
        y++;
        if (y == getHeight() - 25) {
            up = true;
        }
    } else {
        if (x <= getWidth() - 15 && x > 20) {
            g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
            g.drawLine(x + 5, y - 5, x + 5, y + 5);    // wing
            g.drawLine(x + 20, y - 2, x + 20, y + 2);
            x--;
        }
        if (x == 20) {
            g.drawLine(x, y, x, y + 20);               // body - drawn in terms of x
            g.drawLine(x - 5, y + 5, x + 5, y + 5);    // wing
            g.drawLine(x - 2, y + 20, x + 2, y + 20);
            y--;
        }
        if (y == 10) {
            right = true;
        }
    }
}

And that's it! Here's an image showing how it looks like:

就是这样!这是一个显示它的样子的图像:

Java(Swing) - 如何旋转一堆线?

Additional tips:

  1. Don't call frame.setSize() but override MovePlane's JPanel getPreferredSize() to return a fixed size of 300, 300.

    不要调用frame.setSize(),而是覆盖MovePlane的JPanel getPreferredSize()以返回固定大小300,300。

  2. Always place your GUI in the Event Dispatch Thread (EDT) by wrapping your main method like this:

    始终将GUI放在事件调度线程(EDT)中,方法是将主方法包装为:

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Your code here
            }
        });
    }
    
  3. Related to tip #1, call frame.pack(); instead of frame.setSize() after overriding JPanel's getPreferredSize() :)

    与提示#1相关,请调用frame.pack();覆盖JPanel的getPreferredSize()后,而不是frame.setSize():)