有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将JFrame移动到特定位置比使用setLocation()将其“传送”更顺畅?

我正在尝试建立一个方法“move()”,当我用这个方法移动一个JFrame时,我可以用它来设置从开始位置到结束位置的动画。setLocation(intx,inty)方法。我尝试了下面的方法,它将帧放在了正确的位置,但问题是动画首先在x轴上下降,然后才在y轴上下降,但我的目标是使它看起来像是到目标点的对角线运动。我知道这是因为第一个forLoops,因为它们不具备将setLocation方法的过程分解为单个部分的正确条件,但我完全不知道如何解决这个问题

public int currentX() {
    return (int) frame.getLocation().getX();
}

public int currentY() {
    return (int) frame.getLocation().getY();
}

public void move(int x, int y) {
    for (int newX = currentX(); newX < x; newX++) {
        frame.setLocation(currentX() + 1, currentY());
        for(int newY = currentY(); newY < y; newY++) {
            frame.setLocation(currentX(), currentY() + 1);
        }
    }
}

提前谢谢


共 (2) 个答案

  1. # 1 楼答案

    Swing是单线程的,您需要将for-loop从主线程移出。Swing也不是线程安全的,所以对UI状态的任何修改都应该在主线程(事件调度)的上下文中完成——catch 22——最简单的解决方案是使用Swing Timer

    有关更多详细信息,请参见How to use Swing Timers

    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new JLabel("Hello"));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            move(frame, 100, 100);
                        }
                    });
                }
            });
        }
    
        public static void move(JFrame frame, int deltaX, int deltaY) {
            int xMoveBy = deltaX > 0 ? 4 : -4;
            int yMoveBy = deltaY > 0 ? 4 : -4;
    
            int targetX = frame.getX() + deltaX;
            int targetY = frame.getY() + deltaY;
    
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int frameX = frame.getX();
                    int frameY = frame.getY();
                    if (deltaX > 0) {
                        frameX = Math.min(targetX, frameX + xMoveBy);
                    } else {
                        frameX = Math.max(targetX, frameX - xMoveBy);
                    }
                    if (deltaY > 0) {
                        frameY = Math.min(targetY, frameY + yMoveBy);
                    } else {
                        frameY = Math.max(targetY, frameY - yMoveBy);
                    }
    
                    frame.setLocation(frameX, frameY);
                    if (frameX == targetX && frameY == targetY) {
                        ((Timer)e.getSource()).stop();
                    }
                }
            });
            timer.start();
        }
    
    }
    
  2. # 2 楼答案

    第二个循环一直运行到完成,您需要同时移动帧,并且只在需要时增加XY

    public int currentX() {
        return (int) frame.getLocation().getX();
    }
    
    public int currentY() {
        return (int) frame.getLocation().getY();
    }
    
    public void move(int x, int y) {
        for (int newX = currentX(), newY = currentY(); newX < x || newY < y;     ) {
            frame.setLocation(newX, newY);
            if (newX < x) newX++;
            if (newY < y) newY++;
        }
    }