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

时间:2017-10-18 19:11:09

标签: java swing loops jframe location

我正在尝试构建一个方法“move()”,当使用frame.setLocation(int x,int y)方法移动JFrame时,我可以使用该方法设置从开始到结束位置的方式。我尝试了以下内容,它将框架放在正确的位置,但问题是动画首先在x轴上向下,然后仅沿着y轴向下,但我的目标是让它看起来像是一个对角线的运动目的地点。我知道它是因为第一个forLoops因为它们没有将setLocation方法的过程分解为单个部分的正确条件,但我完全不知道如何解决这个问题。

$except

提前谢谢!

2 个答案:

答案 0 :(得分:2)

Swing是单线程,您需要将for-loop从主线程移开。 Swing也不是线程安全的,因此对UI状态的任何修改都应该在main(Event Dispatching)线程的上下文中完成 - 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();
    }

}

答案 1 :(得分:-1)

你的第二个循环一直运行直到完成,你需要同时移动框架,只在需要时增加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++;
    }
}