java - JPanel设置位置

标签 java swing location jpanel

其中写着: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());
        }
    }
}

最佳答案

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

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

查看Concurrency in Swing了解更多详情

已更新

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

您正在与布局管理器作斗争,您会发现一旦您重新验证 usePanel 正在使用的容器,它将重新定位回布局管理器想要组件的位置是。

尝试查看Sliding-Layout寻求更好的解决方案

更新了基本示例

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

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

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

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

enter image description here

此示例使用根 Pane 的玻璃 Pane 功能来提供叠加滑出,请参阅 How to use Root Panes了解更多详情。

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

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

        }
    }
}

关于java - JPanel设置位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19083355/

相关文章:

java - 更改进度条粗细和动画速度

java - JTable 排序不显示图像

java - JTextPane 中的垂直和水平对齐

java - Netbeans Swing UI 设计器 - 危险图标是什么意思?

java - 我可以从 JSONObject 中获取值(value)而无需提及其名称吗?

java - 如何将函数式概念应用到 Java 8 中的传统过程算法中?

google-maps - Location.requestForegroundPermissionsAsync 不是函数

android - map Activity 上的自定义按钮

ios - 让用户随时了解其位置并在 iOS 后台运行的应用程序?

Java - Thymeleaf - HTML : Color letters using switch case: Unwanted paragraph/newline