防止JLabel职位重置?

时间:2015-11-13 23:11:36

标签: java swing jframe jpanel

Pic

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

我现在收到的问题是,当我设置JLabel的时间和位置时,我左边的JLabel会出现问题。它首先出现在它的初始位置(开箱顶部),然后在每个它应该移动的位置移动到它的随机位置。

我有一个实现runnable的类来处理左边的JLabel,另一个类也实现了runnable,它通过时间更新来处理JLabel。

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

这是关注左侧小组的类:

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

1 个答案:

答案 0 :(得分:2)

  

它首先出现在它的初始位置(开箱顶部),然后在每个它应该移动的位置移动到它的随机位置。

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

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

那就是我看不到你在哪里使用pnlMove.setLayout( null )

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

所以我的推荐是:

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

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

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

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