5

我现在有一个问题 - 当我frame.setState(Frame.ICONIFIED)使用自定义按钮调用时(我没有使用默认的 JFrame 最小化按钮 - JFrame 设置为setUndecorated(true)),JFrame 只是进入任务栏而没有任何动画。在正常情况下,它应该逐渐去任务栏最小化自己。但是,如果我在任务栏上按图标化的 JFrame,它会用动画恢复到正常大小。这种情况是在 Windows XP 上,没有在其他系统上测试过,但我想它会以相同的方式运行。

4

3 回答 3

4

由于您希望它独立于平台,因此我的其他答案对您不起作用。此外,当您最小化或隐藏窗口时,每个平台都会做出不同的反应。您提到很高兴看到可以为您提供一致动画的 Java 代码片段。这是给你的一些代码。

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

这是一个实用类,可以让你的未装饰框架淡入或淡出。由于任务栏和最小化窗口的位置会根据平台而变化,并且您需要使用特定于平台的 api 来找到它,所以我只是让动画淡出窗口,而不会将其缩小到任务栏可能所在的位置。

希望这可以帮助!

于 2013-08-30T23:25:10.660 回答
3

如果您说的是真的,并且您未装饰的窗口实际上在单击任务栏中的图标时会显示动画。然后,您可以使用 JNA 在代码中触发相同的操作。

要使此解决方案起作用,您需要在类路径中包含jna.jar和jna -platform.jar

这不是 JNA 教程,周围有很多。这只是使用 JNA 调用 user32.dll 函数CloseWindowOpenIcon的代码;这些是当您单击应用程序的托盘图标时 Windows 调用的函数—— (说实话,我不确定这些是实际的函数,但它们的反应相同)

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

要调用代码,只需像这样传入您的框架或对话框

JFrame frame = new JFrame();
...
IconifyUtilityClass.minimize(frame); //minimize your frame
...
IconifyUtilityClass.restore(frame); //restore your frame

值得注意的是,在 Windows 7 中,未修饰的帧根本不动画(即使使用 user32.dll AnimateWindow函数)。因此,如果您的目标是让您的帧在任何地方进行动画处理,那么您是对的,您必须自己动手。JavaFx 有一些非常好的动画东西可以帮助解决这个问题。

于 2013-08-29T22:41:04.993 回答
2

通过调用

myJFrame.setUndecorated( true )

您正在为您的 JFrame 禁用任何框架装饰。这包括最大化和最小化 JFrame 的动画。

如果您跳过此呼叫或将其更改为

myJFrame.setUndecorated( false )

然后动画将再次可见,即使通过调用最小化框架

myJFrame.setState( Frame.ICONIFIED );

AFAIK,没有办法为未装饰的框架设置动画。:(

请在此处找到我的完整代码示例:

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

问候

克里斯托弗

于 2013-08-29T08:05:14.600 回答