1

它在哪里说: usePanel.setLocation(800,usePanel.getY()); 它没有设置它只是从中间开始的位置,而是在 for 循环中逐渐改变位置以获得一个很酷的动画,它工作正常。

知道为什么启动它的第一个设置位置不起作用吗?顺便说一句,这是在 FlowLayout 下,所以我认为这可能与它有关,但不确定。

        usePanel.setLocation(800,usePanel.getY());
        for(int x=0;x<3500;x+=6){
            usePanel.setLocation(usePanel.getX()-5,usePanel.getY());
            Thread.sleep(500);
        }

用当前代码更新

private Timer nextloc;
private JPanel usePanel;
private static ClosePanel cp = new ClosePanel("null");

public void run(){
    Timer andgo = new Timer(10,new TimerListener());
    while(!cp.getCloseDone()){
        andgo.start();
        andgo.restart();
    }
    if(panel.equals("topiccreator")){
        usePanel=topiccreator;
    }else{
        System.out.println("NULL PANEL TO MOVE!");
        usePanel=mainmenu;
    }

            //This is what is not working
    usePanel.setLocation(usePanel.getX()+800,usePanel.getY());
    usePanel.setVisible(true);

    nextloc = new Timer(50,new TimerListener());
    for(int r=0;r<3500;r+=6){
        nextloc.start();
        nextloc.restart();
    }
}

private class TimerListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
        if(e.getSource()==nextloc){
            usePanel.setLocation(usePanel.getX()-5,usePanel.getY());
        }
    }
}
4

2 回答 2

2

通过调用Thread.sleep,您可能会阻塞事件调度线程,该线程负责处理绘制请求等。这意味着在您的循环真正完成之前,EDT 将无法处理面板的更新位置。

相反,使用javax.swing.Timer...

查看Swing 中的并发以获取更多详细信息

更新

顺便说一句,这是在 FlowLayout 下,所以我认为这可能与它有关,但不确定

您正在与布局管理器作斗争,您会发现一旦您使用了正在使用revalidate的容器usePanel,它将重新定位回布局管理器希望组件所在的位置。

尝试查看Sliding-Layout以获得更好的解决方案

更新了一个基本示例

动画是随时间变化的幻觉。在更新 UI 时,Swing 对开发人员提出了一些相当严格的要求。

除了布局管理器之类的东西,Swing 要求对 UI 的所有交互和修改都在事件调度线程的上下文中完成。它还要求在 EDT 以外的另一个线程中执行任何长时间运行或阻塞的进程。

这使我们陷入了第 22 个问题。我们需要在后台运行,因此我们不会阻止 EDT 处理绘制请求(除其他外),但我们需要从 EDT 的上下文中更新我们的组件......

对我们来说幸运的是,有许多可用的解决方案。您的问题最简单的方法是使用javax.swing.Timer

在此处输入图像描述

此示例使用根窗格的玻璃窗格功能来提供覆盖滑出,有关更多详细信息,请参阅如何使用根窗格

它还使用可变定时动画。也就是说,面板的位置是基于动画中时间的进展,而不是一些固定的增量

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class SlidingPane {

    private SlidePane slidePane = new SlidePane();

    public static void main(String[] args) {
        new SlidingPane();
    }

    public SlidingPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JButton slideButton = new JButton("Slide");
                slideButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        slidePane.slide();
                    }
                });

                JFrame frame = new JFrame("Testing");

                JPanel glassPane = new JPanel(null);
                glassPane.setOpaque(false);
                glassPane.add(slidePane);
                frame.setGlassPane(glassPane);
                glassPane.setVisible(true);

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                frame.add(new JLabel("Look ma, no hands!"), gbc);
                frame.add(slideButton, gbc);
                frame.setSize(400, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class SlidePane extends JPanel {

        private long startTime = -1;
        private int runTime = 1000;
        private int startX;
        private int targetX;
        private boolean slideIn = false;
        private Timer slideTimer;

        public SlidePane() {
            setBackground(Color.DARK_GRAY);
            setBorder(new LineBorder(Color.BLACK));
            setLocation(-getPreferredSize().width, 0);
            setLayout(new GridBagLayout());
            JLabel label = new JLabel("I'm your overload");
            label.setForeground(Color.WHITE);
            add(label);
            slideTimer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long diff = System.currentTimeMillis() - startTime;
                    double progress = (double)diff / (double)runTime;
                    if (progress >= 1d) {
                        progress = 1d;
                        slideTimer.stop();
                        startTime = -1;
                    }

                    Container parent = getParent();
                    int height = parent.getHeight();
                    setSize(getPreferredSize().width, height);

                    int x = calculateProgress(startX, targetX, progress);
                    setLocation(x, 0);
                    revalidate();
                    repaint();
                }
            });
        }

        protected int calculateProgress(int startValue, int endValue, double fraction) {

            int value = 0;
            int distance = endValue - startValue;
            value = (int) Math.round((double) distance * fraction);
            value += startValue;

            return value;

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 400);
        }

        public void slide() {

            slideTimer.stop();
            startTime = System.currentTimeMillis();

            slideIn = !slideIn;
            startX = getX();
            targetX = 0;
            if (!slideIn) {
                targetX = -getPreferredSize().width;
            }

            slideTimer.start();

        }
    }
}
于 2013-09-29T21:33:02.067 回答
0

为什么你认为它不起作用?可能你不能只注意到它。在您第一次setPosition()添加以下代码后:

Thread.sleep(3000);

然后你会注意到它。

于 2013-09-29T21:28:54.340 回答