Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
119 views
in Technique[技术] by (71.8m points)

java - JPanel setLocation

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 position for a cool animation, it works fine.

Any idea why the first set location to get it started isn't working? This is under FlowLayout btw so I assume that may have something to do with it but am not sure.

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

Updated with current code

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());
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...