Java move GUI panel While loop

Tags: , ,



I have a panel. I want to move the panel, inside a while loop, to the left and then to the right, after pressing a button and until a certain condition is met. But for this question let’s say continuously. After it finishes an iteration, it doesn’t move left or right. I used repaint() and Thread.sleep(1000) but nothing shows up. Please help me

while (true) {
    for (int i = 0; i < 5; i++) {
        jPanel1.setLocation(jPanel1.getLocation().x + 5, jPanel1.getLocation().y);
        i++;
        try {Thread.sleep(1000);} catch (InterruptedException ex) {}
        repaint();
    }

    for (int i = 0; i < 5; i++) {
        jPanel1.setLocation(jPanel1.getLocation().x - 5, jPanel1.getLocation().y);
        i++;
        try {Thread.sleep(1000);} catch (InterruptedException ex) {}
        repaint();
    }
}

Answer

We meet again!

I managed to implement the moving JPanel using a Swing timer.

Since you want to move the JPanel, you need to place it in a parent container that is large enough to allow the JPanel to be placed in different locations within it. You also need to use a null layout manager because most layout managers will ignore calls to method setLocation().

More explanations after the code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.WindowConstants;

public class MovePane implements ActionListener, Runnable {
    private static final String  START = "Start";
    private static final String  STOP = "Stop";

    private int  diff;
    private JButton  startButton;
    private JButton  stopButton;
    private JFrame  frame;
    private JPanel  jPanel1;
    private Timer  timer;

    public MovePane() {
        diff = 10;
    }

    @Override // jva.awt.event.ActionListener
    public void actionPerformed(ActionEvent event) {
        String actionCommand = event.getActionCommand();
        switch (actionCommand) {
            case START:
                launchTimer();
                break;
            case STOP:
                stopTimer();
                break;
            default:
                JOptionPane.showMessageDialog(frame,
                                              actionCommand,
                                              "Unhandled",
                                              JOptionPane.WARNING_MESSAGE);
        }
    }

    @Override // java.lang.Runnable
    public void run() {
        showGui();
    }

    private JButton createButton(String text, int mnemonic, String tooltip, boolean enabled) {
        JButton button = new JButton(text);
        button.setMnemonic(mnemonic);
        button.setToolTipText(tooltip);
        button.setEnabled(enabled);
        button.addActionListener(this);
        return button;
    }

    private JPanel createButtonsPanel() {
        JPanel buttonsPanel = new JPanel();
        startButton = createButton(START, KeyEvent.VK_M, "Sets panel in motion.", true);
        buttonsPanel.add(startButton);
        stopButton = createButton(STOP, KeyEvent.VK_P, "Stops panel motion.", false);
        buttonsPanel.add(stopButton);
        return buttonsPanel;
    }

    private JPanel createMainPanel() {
        JPanel mainPanel = new JPanel(null);
        mainPanel.setPreferredSize(new Dimension(400, 400));
        jPanel1 = new JPanel();
        jPanel1.setBounds(10, 200, 50, 50);
        jPanel1.setBorder(BorderFactory.createLineBorder(Color.RED, 2, true));
        mainPanel.add(jPanel1);
        return mainPanel;
    }

    private void launchTimer() {
        if (timer == null) {
            timer = new Timer(0, e -> movePanel());
            timer.setDelay(500);
        }
        timer.start();
        startButton.setEnabled(false);
        stopButton.setEnabled(true);
    }

    private void stopTimer() {
        timer.stop();
        startButton.setEnabled(true);
        stopButton.setEnabled(false);
    }

    private void movePanel() {
        Point location = jPanel1.getLocation();
        if (location.x > 180) {
            diff = -10;
        }
        else if (location.x < 10) {
            diff = 10;
        }
        location.x += diff;
        jPanel1.setLocation(location);
    }

    private void showGui() {
        frame = new JFrame("Move");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(createMainPanel(), BorderLayout.CENTER);
        frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new MovePane());
    }
}

Swing is event driven. Events are added to a queue and then read off the queue and performed. Setting the location of a JPanel is an event. Calling events in a loop just floods the queue with events and some may be lost. That’s why there is the Swing Timer class. In the above code, every half second I change the location of jPanel1.



Source: stackoverflow