与使用setLocation()“传送”它的方式相比,如何更顺利地将JFrame移动到特定位置?

问题描述:

我试图建立一个方法“移动()”,我可以使用frame.setLocation(int x,int y)方法移动JFrame时从开始到结束位置的动画方式。我尝试了以下方法,并将框架放在正确的位置,但问题在于动画首先在x轴上下移,然后才沿y轴下移,但我的目标是使它看起来像是一个对角线运动目的地点。我知道它是因为第一个forloop,因为他们没有合适的条件将setLocation方法的过程分解为单个部分,但我完全不知道如何解决这个问题。与使用setLocation()“传送”它的方式相比,如何更顺利地将JFrame移动到特定位置?

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); 
     } 
    } 
} 

预先感谢您!

+1

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

+0

可能的[有没有办法在Java中动画整个Jframe,以便它移动?](https://*.com/questions/14950694/is-there-a-way-to-animate-an-entire-jframe-in- java-so-it-it) – BaSsGaz

Swing是单线程,您需要将for-loop从主线程移出。秋千也不是线程安全的,所以任何修改UI的状态应的范围内完成主(事件调度)线程 - 捕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(); 
    } 

} 
+0

非常感谢您的快速解决方案。我尝试了你的代码,它完美的工作。现在我真的必须阅读很多关于你使用的东西,因为我不了解它,并认为实现我的想法会容易得多。 – NarcatasCor

+0

@NarcatasCor Swing中的动画并不难,但它需要不同的方法和思维方式 – MadProgrammer

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

这就是我已经尝试过的,尽管这种情况下的动画会以一种诊断方式移动窗口,但最终的位置将是错误的。 – NarcatasCor

+0

这仍然会阻塞事件调度线程,导致OP正在经历的结果没有变化 – MadProgrammer

+0

@MadProgrammer但他清楚地表示“动画首先在x轴上下移,然后才沿y轴下移”这意味着他注意到动画,所以我猜他没有从主线程启动它,这不是他真正的问题!为什么我会修理一些没有损坏的东西! – BaSsGaz