【问题标题】:Moving of an object物体的移动
【发布时间】:2020-09-10 10:17:12
【问题描述】:

任务如下: 蚂蚁在其居住区域的一个地方(例如,[0; 0])以速度 V 直线移动,然后以相同的速度返回它们的出生点。我有问题物体的移动。对象必须在某个点停止并返回起点。我应该如何修复我的代码?我写的一些代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;

class vThread extends Thread{
public void run(){
    new LabSevenFirst();
    System.out.println(Thread.currentThread().getName());
}

}

public class LabSevenFirst extends JPanel implements ActionListener {
private JFrame fr;
double x = 10;
double y = 10;
double r = 10;
public static double T=0, V;
private float x1, y1, x2, y2, xc, yc;
private int t0;
private Timer timer;
private JButton start, stop, apply;
private JLabel forx1, fory1, forx2, fory2, forV;
private JTextField fx1, fy1, fx2, fy2, fV;


public static void main(String[] args) throws InterruptedException {

    vThread mt = new vThread();
    mt.setName("Ants-labours");
    mt.start();

   Thread.yield();//позволяет досрочно завершить квант времени текущей нити
    Thread.sleep(3000);
    System.out.println(Thread.currentThread().getName());
}

LabSevenFirst() {

    t0 = 1000/60;
    timer = new Timer(t0, this);
    timer.setActionCommand("timer");
    fr = new JFrame("Movement of ants-labours");
    fr.setLayout(null);
    fr.setSize(600, 600);
    fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 50, 300, 300);
    start = new JButton("Start");
    stop = new JButton("Stop");
    apply = new JButton("Apply");
    forx1 = new JLabel("x1");
    fory1 = new JLabel("y1");
    forx2 = new JLabel("x2");
    fory2 = new JLabel("y2");
    forV = new JLabel("V");
    fx1 = new JTextField(x1 + "");
    fy1 = new JTextField(y1 + "");
    fx2 = new JTextField(x2 + "");
    fy2 = new JTextField(y2 + "");
    fV = new JTextField(V + "");
    forx1.setBounds(5, 380, 20, 20);
    fory1.setBounds(5, 400, 20, 20);
    forx2.setBounds(5, 420, 20, 20);
    fory2.setBounds(5, 440, 20, 20);
    forV.setBounds(5, 460, 20, 20);
    fx1.setBounds(30, 380, 40, 20);
    fy1.setBounds(30, 400, 40, 20);
    fx2.setBounds(30, 420, 40, 20);
    fy2.setBounds(30, 440, 40, 20);
    fV.setBounds(30, 460, 40, 20);
    start.setActionCommand("start");
    stop.setActionCommand("stop");
    apply.setActionCommand("apply");
    start.addActionListener(this);
    stop.addActionListener(this);
    apply.addActionListener(this);
    start.setBounds(300, 430, 80, 20);
    stop.setBounds(390, 430, 80, 20);
    apply.setBounds(210, 430, 80, 20);
    fr.add(this);
    fr.add(start);
    fr.add(stop);
    fr.add(apply);
    fr.add(forx1);
    fr.add(fory1);
    fr.add(forx2);
    fr.add(fory2);
    fr.add(forV);
    fr.add(fx1);
    fr.add(fy1);
    fr.add(fx2);
    fr.add(fy2);
    fr.add(fV);
    fr.setVisible(true);
}

@Override
protected void paintComponent(Graphics g) {

    int width = getWidth();
    int height = getHeight();
    //System.out.println("width" + width);
    // System.out.println("height" + height);
    g.setColor(Color.yellow);
    g.fillRect(0, 0, width, height);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setStroke(new BasicStroke(3f));
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    //double x = 0.5 * width;
    //double y = 0.5 * height;
    double r = 0.75 * Math.min(x, y);



    double dx,dy;

    double t,l;
    l=Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
   // System.out.println("!!l!!"+l);
    t= l/V;
    //System.out.println("!!t!!"+t);
    g2d.setColor(Color.black);
    if(T<t) {
        dx = ((x2 - x1) / (Math.sqrt(Math.pow(x2 - x1, 2)) + Math.pow(y2 - y1, 2)));
        //System.out.println("!!dx!!" + dx);
        dy = ((y2 - y1) / (Math.sqrt(Math.pow(x2 - x1, 2)) + Math.pow(y2 - y1, 2)));
        //System.out.println("!!dy!!" + dy);
        x += x1 + dx * V * T;//+ dx * (V * T);
        //System.out.println("!!x!!" + x);
        //System.out.println("!!x1!!" + x1);
        y += y1 + dy * V * T;// + dy * (V * T);
        r =  Math.max(0.1 * r, 5);
       // System.out.println("!!y!!" + y);
        //System.out.println("!!y1!!" + x1);

    }


    if (x==x2 && y == y2 && T>t) {

     dx = ((x2 - x1) / (Math.sqrt(Math.pow(x2 - x1, 2)) + Math.pow(y2 - y1, 2)));

        dy = ((y2 - y1) / (Math.sqrt(Math.pow(x2 - x1, 2)) + Math.pow(y2 - y1, 2)));

        x -= x1 + dx * V * T;//+ dx * (V * T);

        y -= y1 + dy * V * T;// + dy * (V * T);
        r = Math.max(0.1 * r, 5);


    }

    g2d.fill(circle(x,y,r));

    //if (x == x2 && y == y2)
    // x = x1 -
}

public Shape circle(double x, double y, double R){

    return new Ellipse2D.Double(x - r, y - r, 2 * r, 2 * r);
}

@Override
public void actionPerformed(ActionEvent e) {
    switch (e.getActionCommand()) {
        case "stop": {
            timer.stop();
            break;
        }
        case "start": {
            timer.start();
            break;
        }
        case "apply": {
            float ax1, ay1, bx2, by2, cv;
            try {
                ax1 = Float.parseFloat(fx1.getText());
                ay1 = Float.parseFloat(fy1.getText());
                bx2 = Float.parseFloat(fx2.getText());
                by2 = Float.parseFloat(fy2.getText());
                cv = Float.parseFloat(fV.getText());
                x1 = ax1;
                y1 = ay1;
                x2 = bx2;
                y2 = by2;
                V = cv;
                repaint();
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(null, "Invalid input", "Error", 
JOptionPane.ERROR_MESSAGE);
            }
            break;
        }
        case "timer": {
            T += 0.6;
            System.out.println("!!T!!"+T);
            repaint();
            break;
   }
  }
 }
}

【问题讨论】:

  • “我在移动物体时遇到问题”是一个不充分的问题描述。描述您对代码的期望与实际作用。请具体说明这些“问题”是什么,以及您认为究竟是什么导致了这些问题。大多数时候,如果您停下来思考自己在做什么,并以有纪律和有条理的方式发现问题,您就可以自己想出解决方案,而不是依赖陌生人的善意。
  • @MarsAtomic,所以我的任务是创建一个从某个点移动的对象,例如坐标为 [0,0] 的边缘到另一点。对象应沿直线移动。我的代码实际上做了什么?我在某个点创建了一个圆,然后输入了它应该移动的坐标,但是当对象到达输入的坐标时它会消失,然后在一段时间后返回。我实际上不知道我的问题在哪里:计时器、循环或数学公式。
  • 在运行一项测试之前,您已经编写了大量代码。这是一个想法。写大概 10 行代码。对其进行测试以确保其正常工作。再写10行代码,测试一下。重复直到完成。尽早测试,经常测试。
  • @GilbertLeBlanc 我试图这样做,但它没有帮助我......我在我的代码中找不到真正的问题。

标签: java user-interface


【解决方案1】:

OP 定义了一个任务:

蚂蚁在其居住区域的一个地方移动(例如, [0; 0]) 以速度 V 直线行驶,然后转回 他们的出生点以相同的速度。我有问题 物体的移动。物体必须停在某个点然后走 回到起点。

然后他问了?

我应该如何修复我的代码?

为时已晚。需要调试和测试的代码行数太多。

让我们重新开始吧。

这是新代码的第一次迭代。

import javax.swing.SwingUtilities;

public class MovingAnts implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MovingAnts());
    }

    public MovingAnts() {

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

    }

}

我们可以通过运行这段代码并观察它它没有异常结束来测试它。

所以,让我们添加更多代码。我们知道我们将不得不定义一只或多只蚂蚁。所以,让我们创建一个Ant 类。

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import javax.swing.SwingUtilities;

public class MovingAnts implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MovingAnts());
    }

    private List<Ant> ants;

    public MovingAnts() {
        ants = new ArrayList<>();

        Point origin = new Point(10, 10);
        Point destination = new Point(200, 300);
        Ant ant = new Ant(5.0d, origin, destination);
        ants.add(ant);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

    }

    public class Ant {

        private final double velocity;

        private Point position;

        private final Point startPosition;
        private final Point endPosition;

        public Ant(double velocity, Point startPosition,
                Point endPosition) {
            this.velocity = velocity;
            this.startPosition = startPosition;
            this.endPosition = endPosition;
        }

        public double getVelocity() {
            return velocity;
        }

        public Point getPosition() {
            return position;
        }

        public void setPosition(Point position) {
            this.position = position;
        }

        public Point getStartPosition() {
            return startPosition;
        }

        public Point getEndPosition() {
            return endPosition;
        }

    }

}

我们已经定义了速度(速度)、起始位置和结束位置。根据任务描述,这些值不会改变,所以我们可以将它们标记为final,并在构造函数中定义它们。

我们还定义了当前位置。当需要在绘图 JPanel 上绘制蚂蚁时,当前位置将很重要。

随着我们开发更多代码,我们可能会向Ant 类添加更多内容。但是现在,我们有一个类来保存蚂蚁的重要变量。

我们定义了一只蚂蚁(Ant 类的一个实例)并将蚂蚁保存在 MovingAnts 构造函数的 List&lt;Ant&gt; 中。我们稍后可以定义更多,但让我们从一只蚂蚁开始。

现在,我们可以为蚂蚁创建JFrame 和绘图JPanel

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class MovingAnts implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MovingAnts());
    }

    private Dimension drawingPanelSize;

    private DrawingPanel drawingPanel;

    private List<Ant> ants;

    public MovingAnts() {
        drawingPanelSize = new Dimension(400, 400);
        ants = new ArrayList<>();

        Point origin = new Point(10, 10);
        Point destination = new Point(200, 300);
        Ant ant = new Ant(5.0d, origin, destination);
        ants.add(ant);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Moving Ants");
        frame.setDefaultCloseOperation(
                JFrame.EXIT_ON_CLOSE);

        drawingPanel = new DrawingPanel(
                drawingPanelSize);
        frame.add(drawingPanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        public DrawingPanel(Dimension drawingPanelSize) {
            this.setPreferredSize(drawingPanelSize);
        }

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

    public class Ant {

        private final double velocity;

        private Point position;

        private final Point startPosition;
        private final Point endPosition;

        public Ant(double velocity, Point startPosition,
                Point endPosition) {
            this.velocity = velocity;
            this.startPosition = startPosition;
            this.endPosition = endPosition;
        }

        public double getVelocity() {
            return velocity;
        }

        public Point getPosition() {
            return position;
        }

        public void setPosition(Point position) {
            this.position = position;
        }

        public Point getStartPosition() {
            return startPosition;
        }

        public Point getEndPosition() {
            return endPosition;
        }

    }

}

请注意每个方法和类是如何简短而中肯的。没有人可以通过一种方法阅读和理解数百行代码。

我们一次添加了一点代码,并通过运行应用程序测试了每一段代码。在他看来,我们有一个 GUI。我们也没有任何异常终止。 GUI 和没有异常结束都很重要。

我们定义了绘图面板的大小。这个很重要。我们不在乎JFrame 有多大。我们关心绘图JPanel 有多大,因此我们可以将蚂蚁保持在绘图面板的范围内。

我们还没有在绘图面板的paintComponent 方法中添加任何代码。在我们这样做之前,我们必须创建一个动画类来更新蚂蚁的位置。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class MovingAnts implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MovingAnts());
    }

    private Animation animation;

    private Dimension drawingPanelSize;

    private DrawingPanel drawingPanel;

    private List<Ant> ants;

    public MovingAnts() {
        drawingPanelSize = new Dimension(400, 400);
        ants = new ArrayList<>();

        Point origin = new Point(200, 200);
        Point destination = new Point(300, 350);
        Ant ant = new Ant(30.0d, origin, destination);
        ants.add(ant);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Moving Ants");
        frame.setDefaultCloseOperation(
                JFrame.EXIT_ON_CLOSE);

        drawingPanel = new DrawingPanel(
                drawingPanelSize);
        frame.add(drawingPanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        animation = new Animation();
        new Thread(animation).start();
    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        public DrawingPanel(Dimension drawingPanelSize) {
            this.setPreferredSize(drawingPanelSize);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, getWidth(), getHeight());

            g.setColor(Color.BLACK);
            for (Ant ant : ants) {
                Point position = ant.getPosition();
                g.fillOval(position.x - 4,
                        position.y - 4, 8, 8);
            }
        }
    }

    public class Animation implements Runnable {

        private volatile boolean running;

        public Animation() {
            this.running = true;
        }

        @Override
        public void run() {
            int fps = 20;
            long delay = 1000L / fps;

            while (running) {
                calculateAntPosition(fps);
                updateDrawingPanel();
                sleep(delay);
            }

        }

        private void calculateAntPosition(int fps) {
            for (Ant ant : ants) {
                ant.calculatePosition(fps);
//              System.out.println(ant.getPosition());
            }
        }

        private void updateDrawingPanel() {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    drawingPanel.repaint();
                }
            });
        }

        private void sleep(long duration) {
            try {
                Thread.sleep(duration);
            } catch (InterruptedException e) {
                // Deliberately left empty
            }
        }

        public synchronized void setRunning(
                boolean running) {
            this.running = running;
        }

    }

    public class Ant {

        private boolean returning;

        private double totalDistance;
        private double traveledDistance;
        private double theta;

        private final double velocity;

        private Point position;

        private final Point startPosition;
        private final Point endPosition;

        public Ant(double velocity, Point startPosition,
                Point endPosition) {
            this.velocity = velocity;
            this.startPosition = startPosition;
            this.position = startPosition;
            this.endPosition = endPosition;
            this.returning = false;
            this.theta = calculateTheta();
            this.totalDistance = calculateTotalDistance();
            this.traveledDistance = 0d;
        }

        private double calculateTheta() {
            return Math.atan2((endPosition.y - startPosition.y),
                    endPosition.x - startPosition.x);
        }

        private double calculateTotalDistance() {
            double diffX = endPosition.x - startPosition.x;
            double diffY = endPosition.y - startPosition.y;
            return Math.sqrt((diffX * diffX) + (diffY * diffY));
        }

        public double getVelocity() {
            return velocity;
        }

        public Point getPosition() {
            return position;
        }

        public void calculatePosition(int fps) {
            double distance = velocity / fps;
            double angle = theta;

            if (returning) {
                angle += Math.PI;
            }

            int x = (int) Math.round(
                    position.x + distance * Math.cos(angle));
            int y = (int) Math.round(
                    position.y + distance * Math.sin(angle));

            traveledDistance += distance;
            if (traveledDistance > totalDistance) {
                returning = !returning;
                traveledDistance = 0d;
            }

            this.position = new Point(x, y);
        }

        public Point getStartPosition() {
            return startPosition;
        }

        public Point getEndPosition() {
            return endPosition;
        }

    }

}

我在这次迭代中添加了太多代码,但我们现在有一只蚂蚁在两点之间来回走动。

Animation 类是在Thread 中运行的Runnable。您可以使用 Swing Timer,但我更容易创建 Runnable

Ant 班级长出了一些胸毛。所有的三角计算都可以在Ant 类中找到。基本上,我使用极坐标来计算蚂蚁的位置。

绘图面板的paintComponent 方法只是简单地绘制蚂蚁。

每个方法和类都很小,希望很容易理解。编写简短的方法。编写简短的课程。

希望此代码将为您扩展项目提供坚实的基础。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2011-09-09
    相关资源
    最近更新 更多