java swing 制作平滑过渡动画以调整 Jframe 高度

java swing make a smooth transition animation for resizing Jframe height

提问人:jes 提问时间:10/20/2023 最后编辑:Mark Rotteveeljes 更新时间:10/22/2023 访问量:75

问:

我正在开发一个小型 GUI 应用程序,我打算在按下按钮后调整 JFrame 的大小。我设法调整了 JFrame 的大小,但我想为这个 JFrame 的打开和关闭创建一个流畅的动画。我不确定从哪里开始以及如何开始。我知道我可以想象按下按钮将运行线程/方法并调整 JFrame 的大小。我将尝试通过一些屏幕截图提供尽可能多的细节。

这是 before - before JFrame 调整大小

这是 after - after JFrame 调整大小

JFrame 的当前调整大小的代码

changeBottomFrame.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if(!heightIncreased[0]){
            try{
                frame.setSize(frame.getWidth(), frame.getHeight()+80);
                if(frame.getHeight()==450){
                    frame.add(bottomFrame, BorderLayout.PAGE_END);
                    changeBottomFrame.setText("∨");
                    heightIncreased[0] =true;
                }
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

        } else if (heightIncreased[0]) {
            try {
                frame.setSize(frame.getWidth(), frame.getHeight() - 80);
                if(frame.getHeight()==370) {
                    frame.remove(bottomFrame);
                    changeBottomFrame.setText("∧");
                    heightIncreased[0] = false;
                }
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
        {}
    }
});

在屏幕截图中,我添加了一个 JPanel 来突出显示添加的面积,并显示在代码中,您可以看到以进行澄清。frame.add(bottomFrame)

我是 Java 编码的新手,我已经在 Python GUI 中进行了平滑的动画过渡,但我对 Java Swing 没有经验。

Java Swing 用户界面 jframe jPanel

评论

1赞 davidalayachew 10/20/2023
帧的屏幕截图很好,但不要发布代码的屏幕截图。实际上,将您的代码复制并粘贴到问题中。
1赞 camickr 10/20/2023
我可以想象按下按钮将运行线程/方法并调整 JFrame 的大小。- 实际上,您会使用Swing Timer进行动画制作。每次计时器触发时,您都会调整帧位置/大小。查看:stackoverflow.com/a/54028681/131872 动画示例。我对 Java swing 没有经验另请查看如何使用摆动计时器了解定时器基础知识,并随时提供指向所有摆动基础知识的教程链接。
0赞 jes 10/21/2023
好的好吧,对不起代码截图,我现在就编辑它,也谢谢你提供摆动计时器的想法,我会研究的。我很感激。
0赞 davidalayachew 10/21/2023
@jes 是的,摆动计时器对于创造流畅的效果是明智的。你还应该研究一下 -- docs.oracle.com/en/java/javase/21/docs/api/java.desktop/java/... -- 它给你 -- docs.oracle.com/en/java/javase/21/docs/api/java.desktop/java/... -- 它给你的状态 -- docs.oracle.com/en/java/javase/21/docs/api/java.desktop/java/... Window::addWindowStateListenerWindowStateListener::windowStateChangedWindowEvent
0赞 davidalayachew 10/21/2023
如果不清楚,扩展 ,这 docs.oracle.com/en/java/javase/21/docs/api/java.desktop/java/......WindowEventComponentEvent

答:

0赞 DevilsHnd - 退した 10/21/2023 #1

下面是一个可运行的演示,演示了如何做到这一点。用于对 JFrame 窗口的打开、扩展和关闭进行动画处理的方法位于名为 和 的 AnimateForm 类中。该方法利用 Swing Timer,该方法利用循环对窗体的关闭进行动画处理。animateForm()animateFormClose()animateForm()animateFormClose()while

enter image description here

请记住,这只是一个简单的演示。


SwingFormAnimationDemo 类:

public class SwingFormAnimationDemo {

    private javax.swing.JFrame frame;
    private javax.swing.JPanel rootPanel;
    private javax.swing.JButton resizeButton;

    private int desiredFormWidth = 500;
    private int desiredFormHeight = 300;
    private int widthIncrement = 10;
    private int heightIncrement = 10;
    private int speed = 5;
    private int initialDelay = 300;

    private int desiredFormExtentionWidthAmount = 0;
    private int desiredFormExtentionHeightAmount = 100;
    private int extensionWidthIncrement = 3;
    private int extensionHeightIncrement = 3;
    private int extentionSpeed = 10;
    private int extensionInitialDelay = 300;

    private AnimateForm animate;

    public SwingFormAnimationDemo() {
        initForm();
        animate = new AnimateForm();
        animate.animateForm(frame, desiredFormWidth, desiredFormHeight,
                widthIncrement, heightIncrement, speed, initialDelay);

        frame.addWindowListener(new java.awt.event.WindowListener() {
            @Override
            public void windowOpened(java.awt.event.WindowEvent e) {
                // Do Nothing...
            }

            @Override
            public void windowClosing(java.awt.event.WindowEvent e) {
                animate.animateFormClose(frame);
                if (AnimateForm.animateFormTimer.isRunning()) {
                    AnimateForm.animateFormTimer.stop();
                }
                frame.dispose();
            }

            @Override
            public void windowClosed(java.awt.event.WindowEvent e) {
                // Do Nothing...
            }

            @Override
            public void windowIconified(java.awt.event.WindowEvent e) {
                // Do Nothing...
            }

            @Override
            public void windowDeiconified(java.awt.event.WindowEvent e) {
                // Do Nothing...
            }

            @Override
            public void windowActivated(java.awt.event.WindowEvent e) {
                // Do Nothing...
            }

            @Override
            public void windowDeactivated(java.awt.event.WindowEvent e) {
                // Do Nothing...
            }
        });
        
        resizeButton.addActionListener((java.awt.event.ActionEvent e) -> {
            if (resizeButton.getText().equals("Longer Form")) {
                animate.animateForm(frame, frame.getWidth() + desiredFormExtentionWidthAmount,
                        frame.getHeight() + desiredFormExtentionHeightAmount,
                        extensionWidthIncrement, extensionHeightIncrement,
                        extentionSpeed, extensionInitialDelay);
                resizeButton.setText("Shorter Form");
            }
            else {
                animate.animateForm(frame, frame.getWidth() - desiredFormExtentionWidthAmount,
                        frame.getHeight() - desiredFormExtentionHeightAmount,
                        extensionWidthIncrement, extensionHeightIncrement,
                        extentionSpeed, extensionInitialDelay);
                resizeButton.setText("Longer Form");
            }
        });
    }

    public static void main(String[] args) {
        new SwingFormAnimationDemo().startApp(args);
    }

    private void startApp(String[] args) {
        java.awt.EventQueue.invokeLater(() -> {
            frame.setVisible(true);
            frame.setLocationRelativeTo(null);
        });

    }

    private void initForm() {
        frame = new javax.swing.JFrame();
        frame.setTitle("Swing Form Animation Demo");
        frame.setAlwaysOnTop(true);
        frame.setDefaultCloseOperation(javax.swing.JFrame.DO_NOTHING_ON_CLOSE);
        frame.setPreferredSize(new java.awt.Dimension(0, 0));
        
        rootPanel = new javax.swing.JPanel();

        resizeButton = new javax.swing.JButton("Longer Form");
        rootPanel.add(resizeButton);

        javax.swing.JTable table = new javax.swing.JTable(17, 3);
        table.setShowHorizontalLines(true);
        table.setShowVerticalLines(true);
        table.setGridColor(java.awt.Color.LIGHT_GRAY);
        javax.swing.JScrollPane sp = new javax.swing.JScrollPane(table);
        sp.setPreferredSize(new java.awt.Dimension(400, 300));
        rootPanel.add(sp);

        frame.setContentPane(rootPanel);
        frame.pack();
    }
}

AnimateForm 类:

public class AnimateForm {

    public static javax.swing.Timer animateFormTimer;

    public void animateForm(javax.swing.JFrame suppliedFrame, int width, int height,
            int widthIncrement, int heightIncrement, int speed, int initialDelay) {
        animateFormTimer = new javax.swing.Timer(speed, (java.awt.event.ActionEvent evt) -> {
            boolean widthRetraction = width < suppliedFrame.getWidth();
            boolean heightRetraction = height < suppliedFrame.getHeight();

            // Form animation...
            if (width > suppliedFrame.getWidth()) {
                suppliedFrame.setSize(suppliedFrame.getWidth() + widthIncrement,
                        suppliedFrame.getHeight());
            }
            else if (width < suppliedFrame.getWidth()) {
                suppliedFrame.setSize(suppliedFrame.getWidth() - widthIncrement,
                        suppliedFrame.getHeight());
            }
            else {
                suppliedFrame.setSize(width, suppliedFrame.getHeight());
            }

            if (height > suppliedFrame.getHeight()) {
                suppliedFrame.setSize(suppliedFrame.getWidth(),
                        suppliedFrame.getHeight() + heightIncrement);
            }
            else if (height < suppliedFrame.getHeight()) {
                suppliedFrame.setSize(suppliedFrame.getWidth(),
                        suppliedFrame.getHeight() - heightIncrement);
            }
            else {
                suppliedFrame.setSize(suppliedFrame.getWidth(), height);
            }

            if ((widthRetraction ? suppliedFrame.getWidth() <= width : suppliedFrame.getWidth() >= width)
                    && (heightRetraction ? suppliedFrame.getHeight() <= height : suppliedFrame.getHeight() >= height)) {
                animateFormTimer.stop();
            }
        });
        animateFormTimer.setInitialDelay(initialDelay);
        animateFormTimer.start();
    }

    public void animateFormClose(javax.swing.JFrame frame) {
        while (frame.getWidth() > 140 || frame.getHeight() > 40) {
            frame.setSize(frame.getWidth() - 1, frame.getHeight() - 1);
        }
    }
}

评论

0赞 davidalayachew 10/21/2023
哦,太酷了。我本来会用 WindowStateListener 来做到这一点,但这也有效。
0赞 jes 10/22/2023
是的,这个对我来说效果很好。我实现了一些额外的变量,并将其与我的代码相结合,并设法让它工作。非常感谢你 - 对不起,我会投票,但我没有足够的声誉哈哈