问题
I have a problem now - when I call frame.setState(Frame.ICONIFIED) with my custom button (I'm not using default JFrame minimize button - JFrame set to setUndecorated(true) ), the JFrame just goes to Taskbar without any animation. In normal situation it should gradually go to Taskbar minimizing itself. But if I press iconfied JFrame on Taskbar, it restores with animation to normal size. The situation is on Windows XP, not tested on other systems, but I suppose it would behave in the same way.
回答1:
If what you are saying is true, and your undecorated windows do in fact animate when clicking the icons in the task bar. Then you can trigger that same action in your code using JNA.
For this solution to work, you'll need to include jna.jar and jna-platform.jar in your classpath.
This isn't a JNA tutorial, there are plenty of those around. This is just code that uses JNA to call the user32.dll functions CloseWindow and OpenIcon; These are the functions that Windows calls when you click the application's tray icon -- (truth be told I'm not certain that these are the actual functions, but they react the same).
import java.awt.Component;
import java.awt.Window;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.HWND;
public class IconifyUtilityClass
{
public static void minimize(Window window)
{
HWND hWnd = getHWND(window);
User32dll.INSTANCE.CloseWindow(hWnd); //call CloseWindow with this windows handle
}
public static void restore(Window window)
{
HWND hWnd = getHWND(window);
User32dll.INSTANCE.OpenIcon(hWnd); //call OpenIcon with this windows handle
}
private interface User32dll extends Library
{
User32dll INSTANCE = (User32dll) Native.loadLibrary("user32.dll", User32dll.class);
boolean OpenIcon(HWND hWnd);
boolean CloseWindow(HWND hWnd);
}
private static HWND getHWND(Component comp)
{
return new HWND(Native.getComponentPointer(comp));
}
}
To call the code just pass in your frame or dialog like so
JFrame frame = new JFrame();
...
IconifyUtilityClass.minimize(frame); //minimize your frame
...
IconifyUtilityClass.restore(frame); //restore your frame
It's worth noting that in Windows 7 undecorated frames don't animate at all (even using the user32.dll AnimateWindow function). So if your goal is to get your frames to animate anywhere, you are right, you'll have to do it yourself. JavaFx has some really nice animation stuff that would help with this.
回答2:
Since you want it to be platform independent, my other answer will not work for you. Also, each platform will react differently when you minimize or hide a window. You mentioned it would be nice to see a Java code fragment that would give you a consistent animation. Here's some code for you.
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
public class FadeUtilityClass
{
private static final int TIME = 200;
private static final int MILLIS_PER_FRAME = 33;
private static final float DELTA = MILLIS_PER_FRAME / (float)TIME; //how much the opacity will change on each tick
/**
* @param frame the frame to fade in or out
* @param in true if you are fading in, false if you're fading out
*/
public static void fade(final JFrame frame, final boolean in)
{
frame.setOpacity(in ? 0f : 1f); //if we're fading in, make sure our opacity is 0, and 1 if we're fading out
if (in) //set the state back to normal because we might have been minimized
frame.setState(JFrame.NORMAL);
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask()
{
float opacity = in ? 0f : 1f;
float delta = in ? DELTA : -DELTA;
@Override
public void run()
{
opacity += delta; //tweak the opacity
if (opacity < 0) //we're invisible now
{
frame.setState(JFrame.ICONIFIED); //hide frame
frame.setOpacity(1f); //then make it opaque again, so it'll reappear properly if they click the taskbar
timer.cancel(); //stop the timer
}
else if (opacity > 1) //we're fully visible now
{
frame.setOpacity(1f); //make the opacity an even 1.0f
timer.cancel(); //stop the timer
}
else
frame.setOpacity(opacity);
}
};
timer.scheduleAtFixedRate(timerTask, MILLIS_PER_FRAME, MILLIS_PER_FRAME);
}
}
It's a utility class that will make your undecorated frame fade in or out. Since the location of the taskbar and minimized window changes based on the platform and you would need to use platform specific api's to find that, I just made the animation fade the window out without shrinking it down to where the taskbar might be.
Hope this helps!
回答3:
by calling
myJFrame.setUndecorated( true )
You're disabling any frame decorations for your JFrame. This includes the animations on maximizing and minimizing your JFrame.
If you skip this call or change it to
myJFrame.setUndecorated( false )
then the animations will be visible again, even by minimizing the frame with a call to
myJFrame.setState( Frame.ICONIFIED );
AFAIK, there is no way to animate an undecorated frame. :(
Please find my full code sample here:
JFrame frame = new JFrame();
frame.setSize( 800, 600 );
frame.setUndecorated( false ); // will enable animations
frame.setVisible( true );
try { Thread.sleep( 3000 ); } catch ( Throwable t ) {}
frame.setState( Frame.ICONIFIED );
Greetings
Christopher
来源:https://stackoverflow.com/questions/17761134/jframe-transition-effect-when-called-setstateframe-iconified-it-just-goes-to