JPanel setLocation

前端 未结 2 1780
眼角桃花
眼角桃花 2020-12-12 05:23

Where it says: usePanel.setLocation(800,usePanel.getY()); it doesn\'t set the location it just starts in the middle, but inside the for loop where it gradually changes the p

相关标签:
2条回答
  • 2020-12-12 05:53

    By calling Thread.sleep, you are likely blocking the Event Dispatching Thread, which is responsible for, amongst other things, processing paint requests. This means until your loop actually finishes, the EDT won't be able to process the updated location of your panel.

    Instead, use a javax.swing.Timer...

    Check out Concurrency in Swing for more details

    Updated

    This is under FlowLayout btw so I assume that may have something to do with it but am not sure

    You are fighting the layout manager, you will find that once you revalidate the container that usePanel is using, it will reposition back to where the layout manager wants the component to be.

    Try taking a look at Sliding-Layout for an better solution

    Updated with a basic example

    Animation is the illusion of change over time. Swing places some rather strict requirements on developers when it comes to updating the UI.

    Apart from things like layout managers, Swing requires that all interactions and modifications to the UI be done within the context of the Event Dispatching Thread. It also requires that any long running or block process be executed in another thread other than the EDT.

    This places us in a catch 22. We need to run in the background so we don't stop the EDT from processing paint requests (amongst other things), but we need to update our components from within the context of the EDT...

    Lucky for us, there are a number of solutions available. The simplest to your problem would be the use of a javax.swing.Timer

    enter image description here

    This example uses the glass pane capabilities of the root pane to provide an overlying slide out, see How to use Root Panes for more details.

    It also uses a variable timed animation. That is, the position of the panel is based on the progression of time through the animation rather than some fixed delta

    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();
    
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-12 05:55

    Why you think it is not working? Probably you cannot just notice it. After your first setPosition() add following code:

    Thread.sleep(3000);
    

    Then you will notice it.

    0 讨论(0)
提交回复
热议问题