【问题标题】:How to make a JButton move along with drawn lines如何使 JButton 与绘制的线条一起移动
【发布时间】:2013-08-10 06:52:55
【问题描述】:

我有 Jbutton(由信封表示)和一个 ArrayList 行,信封将沿着这些行。谁能帮我?任何想法或教程将不胜感激。

【问题讨论】:

  • 是否需要JButton,如果你可以使用简单的JLabel/JPanel,如果你没有对这个信封实体执行任何操作。不管怎样,你可以从this 那里得到一些想法,尽管你可以改进逻辑上的东西。
  • 我确实需要 JButton,因为当我点击它时会出现一个弹出菜单。
  • 任何组件都可以附加一个 MouseListerner,只是说

标签: java swing timer runnable animated


【解决方案1】:

我假设您的目标是沿线为信封设置动画,以提供正在传输的数据的动画。

对于每一行,您首先需要找到行方程。线方程的形式为y = a * x + b。如果您已经在List 中提到了它,那很好。另一方面,如果您有两个点(开始和结束位置),请使用上述等式找到每条线的ab

获得线条方程后,您可以使用动画(可能使用SwingWorkerSwingTimer)定期增加信封的x 坐标,然后使用线条方程计算新的y 坐标。

希望对你有帮助

更新:添加了代码 sn-p 用于使用 SwingTimer 进行演示的移动框

package keymovement;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class TestMovingObject {

    static class Envelope {
        double x;
        double y;

        void setPosition(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }

    static class DrawArea extends JPanel {

        Envelope envelope = new Envelope();

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.red);
            int x = (int) Math.round(envelope.x);
            int y = (int) Math.round(envelope.y);
            g.drawRect(x, y, 20, 20);
        }

        public Envelope getEnvelope() {
            return envelope;
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        SwingUtilities.invokeLater( new Runnable() {

            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

                JFrame window = new JFrame("Moving box");
                window.setPreferredSize(new Dimension(500, 400));
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final DrawArea mainArea = new DrawArea();
                window.add(mainArea);
                window.pack();

                window.setLocationRelativeTo(null);
                window.setVisible(true);

                int delay = 20; // execute every 20 milliseconds i.e. 50 times per second  

                Timer timer = new Timer(delay, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        Envelope envelope = mainArea.getEnvelope();
                        double x = envelope.x + 1;  // use smaller increments depending on the desired speed
                        double y = 0.5 * x + 2;     // moving along the line y = 0.5 * x + 2
                        envelope.setPosition(x, y);
                        mainArea.repaint();
                    }
                });
                timer.setRepeats(true);
                timer.start();

            }
        });
    }

}

【讨论】:

  • 感谢您的帮助!我部分知道该怎么做,关于 Swingworker 和 SwingTimer,你能告诉我一个非常简单的例子吗?因为这是我第一次遇到可运行的东西。
  • @ht.luvit 查看我的更新答案。使用SwingTimer 沿线移动框的一个相当粗略的示例
  • 非常感谢您的帮助 :)
【解决方案2】:

你能告诉我一个非常简单的例子吗?

game 中,敌人每次向玩家前进一行或一列,不计算任何中间点。当目的地静止时,路径是一条直线。动画的节奏是javax.swing.Timer。实现见RCModel#move()RCView#timer

【讨论】:

    【解决方案3】:

    有一些数学事情要为你做。 看看这篇文章:http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

    这个简单的算法会告诉你两点之间的直线上的每个 X、Y 坐标。您可以使用此算法计算它需要访问的所有位置,将坐标存储在数组中,并在更新位置时遍历数组。

    还有一个替代的辅助类:

    package snippet;
    
    import java.awt.geom.Point2D;
    
    public class MyVelocityCalculator {
    
        public static void main(String[] args) {
            Point2D.Double currentPosition = new Point2D.Double();
            Point2D.Double destinationPosition = new Point2D.Double();
            currentPosition.setLocation(100, 100);
            destinationPosition.setLocation(50, 50);
            Double speed = 0.5;
    
            System.out.println("player was initially at: " + currentPosition);
            while (currentPosition.getX() > destinationPosition.getX()
                    && currentPosition.getY() > destinationPosition.getY()) {
    
                Point2D.Double nextPosition = MyVelocityCalculator.getVelocity(currentPosition, destinationPosition, speed);
                System.out.println("half seconds later player should be at: " + nextPosition);
    
                currentPosition = nextPosition;
    
            }
            System.out.println("player destination is at: " + destinationPosition);
    
        }
    
        public static final Point2D.Double getVelocity(Point2D.Double currentPosition, Point2D.Double destinationPosition,
                double speed) {
            Point2D.Double nextPosition = new Point2D.Double();
            double angle = calcAngleBetweenPoints(currentPosition, destinationPosition);
            double distance = speed;
            Point2D.Double velocityPoint = getVelocity(angle, distance);
            nextPosition.x = currentPosition.x + velocityPoint.x;
            nextPosition.y = currentPosition.y + velocityPoint.y;
            return nextPosition;
        }
    
        public static final double calcAngleBetweenPoints(Point2D.Double p1, Point2D.Double p2) {
            return Math.toDegrees(Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX()));
        }
    
        public static final Point2D.Double getVelocity(double angle, double speed) {
            double x = Math.cos(Math.toRadians(angle)) * speed;
            double y = Math.sin(Math.toRadians(angle)) * speed;
            return (new Point2D.Double(x, y));
        }
    }
    

    您需要在该位置绘制控件到您的图形元素,而不是打印控制台上的位置。

    【讨论】:

      猜你喜欢
      • 2012-06-14
      • 1970-01-01
      • 2019-10-01
      • 2011-08-27
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      相关资源
      最近更新 更多