java - 防止 JLabel 位置重置?

标签 java swing jframe jpanel

Pic

在左侧面板上,我希望我的 JLabel 移动到框中的随机位置,在右侧面板上,我希望我的 JLabel 经常更新为当前时间,同时也移动到框中的随机位置。

我目前遇到的问题是,当我设置 JLabel 的时间和位置时,我的 JLabel 在我的左框中出现错误。它首先出现在它的初始位置(盒子的顶部),然后每次它应该移动到它的随机位置。

我有一个类实现了处理左侧 JLabel 的 runnable,另一个类也实现了处理带有时间更新的 JLabel 的 runnable。

谁能帮我解决这个问题吗?我希望这个程序以这种方式设置,2 个类实现可处理 JLabels 移动的 runnable。

这是关心左侧面板的类:

public class MoveDisplay {
    private GUIFrame gui;
    private boolean moving = true;


    public MoveDisplay(GUIFrame gui) {
        this.gui = gui;
    }

    public void start() {
        moving = true;
        Random rand = new Random();
        while (moving) {
            int x = rand.nextInt(150) + 1;
            int y = rand.nextInt(150) + 1;

             java.awt.EventQueue.invokeLater(new Runnable() { 
                    public void run() {

                        gui.moveDisplay(x, y, 100, 100);
                    }
                } );
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void stop() {
        moving = false;
    }
}

这是右侧的面板,即时钟。

public class MoveClock {
        private GUIFrame gui;
        private boolean clock = true;
        private volatile boolean running = true;

        public MoveClock(GUIFrame gui) {
            this.gui = gui;
        }

        public void start() {
            clock = true;
            Random rand = new Random();
            while (clock) {

                 Calendar cal = Calendar.getInstance();
                  int hour = cal.get(Calendar.HOUR_OF_DAY);
                  int minute = cal.get(Calendar.MINUTE);
                  int second = cal.get(Calendar.SECOND);
                 gui.Klockan(hour, minute, second);
                  int a = rand.nextInt(100) + 1;
                  int b = rand.nextInt(100) + 1;

                  java.awt.EventQueue.invokeLater(new Runnable() { //Utan detta så kör inte Klockan random placeringar
                        public void run() {

                            gui.moveClock(a, b, 150, 150);
                        }
                    } );


                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public void stop() {
            clock = false;
        }
    }

这是所有 Frame、Jpanels 等类的所在:

    private JLabel movingDisplay;
    private JLabel movingClock;
    private MP3Player mp3_player;
    private boolean playing = true;
    private boolean moving = true;
    private boolean clocking = true;
//  private Thread t1;
    JDialog playingDialog;
    private MoveDisplay moveDisplay;
    private MoveClock moveClock;

    Clip clip;

    /**
     * Starts the application
     */
    public void Start() {
        frame = new JFrame();
        frame.setBounds(0, 0, 494, 437);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //frame.setLayout(null);
        frame.setTitle("Multiple Thread Demonstrator");
        InitializeGUI(); // Fill in components
        frame.setVisible(true);
        frame.setResizable(false); // Prevent user from change size
        frame.setLocationRelativeTo(null); // Start middle screen
        moveDisplay = new MoveDisplay(this);
        moveClock = new MoveClock(this);
    }

JPanel pnlDisplay = new JPanel();
        Border b2 = BorderFactory.createTitledBorder("Display Thread");
        pnlDisplay.setBorder(b2);
        pnlDisplay.setBounds(12, 118, 222, 269);
        pnlDisplay.setLayout(null);

        // Add buttons and drawing panel to this panel
        btnDisplay = new JButton("Start Display");
        btnDisplay.setBounds(10, 226, 121, 23);
        pnlDisplay.add(btnDisplay);

        btnDStop = new JButton("Stop");
        btnDStop.setBounds(135, 226, 75, 23);
        pnlDisplay.add(btnDStop);

        pnlMove = new JPanel();
        pnlMove.setBounds(10, 19, 200, 200);
        Border b21 = BorderFactory.createLineBorder(Color.black);
        pnlMove.setBorder(b21);
        pnlDisplay.add(pnlMove);
        // Then add this to main window
        frame.add(pnlDisplay);

        // The moving graphics outer panel
        JPanel pnlTriangle = new JPanel();
        Border b3 = BorderFactory.createTitledBorder("Triangle Thread");
        pnlTriangle.setBorder(b3);
        pnlTriangle.setBounds(240, 118, 222, 269);
        pnlTriangle.setLayout(null);

        // Add buttons and drawing panel to this panel
        btnTriangle = new JButton("Start Rotate");
        btnTriangle.setBounds(10, 226, 121, 23);
        pnlTriangle.add(btnTriangle);

        btnTStop = new JButton("Stop");
        btnTStop.setBounds(135, 226, 75, 23);
        pnlTriangle.add(btnTStop);

        pnlRotate = new JPanel();
        pnlRotate.setBounds(10, 19, 200, 200);
        Border b31 = BorderFactory.createLineBorder(Color.black);
        pnlRotate.setBorder(b31);
        pnlTriangle.add(pnlRotate);
        // Add this to main window
        frame.add(pnlTriangle);



        movingDisplay = new JLabel("DisplayThread");
        pnlMove.add(movingDisplay);
        btnDStop.setEnabled(false);


        movingClock = new JLabel("TriangleThread");
        pnlRotate.add(movingClock);
        btnTStop.setEnabled(false);


        btnDisplay.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                moving = true;
                btnDisplay.setEnabled(false);
                btnDStop.setEnabled(true);
                startMoveDisplay();
            }
        });

        btnDStop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                moving = false;
                btnDisplay.setEnabled(true);
                btnDStop.setEnabled(false);
                startMoveDisplay();
            }
        });

        btnTriangle.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                clocking = true;
                btnTriangle.setEnabled(false);
                btnTStop.setEnabled(true);
                startMoveClock();
            }
        });


    btnTStop.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            clocking = false;
            btnTriangle.setEnabled(true);
            btnTStop.setEnabled(false);
            startMoveClock();
        }
    });
}

    public void startMoveDisplay() {
        if(moving) {
            new Thread(new Runnable() {
                public void run() {
                    moveDisplay.start();
                }
            }).start();
        } else {
            moveDisplay.stop();
        }
    }

    public void startMoveClock() {
        if(clocking) {
            new Thread(new Runnable() {
                public void run() {
                    moveClock.start();
                }
            }).start();
        } else {
            moveClock.stop();
        }
    }

    public void moveDisplay(int x, int y, int width, int height) {
        movingDisplay.setBounds(x, y, width, height);
    }

    public void moveClock(int a, int b, int width, int height) {
        movingClock.setBounds(a, b, width, height);
    }

    public void Klockan(int hour, int minute, int second) {
        movingClock.setText(hour + ":" + minute + ":" + second);
    }

最佳答案

It appears at it's initial position first (top of the box) before moving to it's random position every it's supposed to move.

嗯,您的整个程序使用空布局(这是不正确的,因为 Swing 被设计为与布局管理器一起使用),除了您添加随机标签的面板。

    movingDisplay = new JLabel("DisplayThread");
    pnlMove.add(movingDisplay);

也就是说,我不知道你在哪里使用pnlMove.setLayout( null )

所以我猜测布局管理器被暂时调用,并且标签在面板移动到随机位置之前被绘制在面板的开头。

所以我的建议是:

  1. 不要使用空布局构建 GUI(具有随机位置的面板除外)。 Swing 被设计为与布局管理器一起使用。

  2. 不要使用 Thread 和 Thread.sleep()。对于动画,请使用 Swing Timer。当计时器触发时,代码将在 EDT 上执行,并且您不需要 SwingUtilities.invokeLater()。

  3. 您希望代码做的就是更改标签的位置,因此只需使用 setLocation(...) 方法,而不是 setBounds() 方法。

  4. 方法名称不应以大写字符开头。你的大部分名字都是正确的。始终如一!请注意论坛如何突出显示方法名称,就像它们是类名称一样?

关于java - 防止 JLabel 位置重置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33703206/

相关文章:

java - 如何调整jws小程序窗口的大小?

java - 保存自定义类时出现 NotSerializableException

java - 处理 JPA/DAO 实体结果中的非数据库映射字段

java - grails 3加载图像外部文件夹

java - JTable 包含所有组件

Java - 调用paintComponent方法

java - 从内部类 : needs to be declared final error java swing 中访问局部变量

java - 设置 JWindow 背景图像

java - JFrame 未显示

swing - 我无法在 NetBeans (jframe) 中进入设计模式