I'm currently trying to get a JLabel
to move across the screen using a SwingWorker.
I can get the JLabel
to update the text in the SwingWoker
but I can't make it change its position.
Here is what I have currently tried
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class MainFrame
{
public MainFrame()
{
addComponents();
}
public void addComponents()
{
JFrame mainFrame = new JFrame("Some Frame");
JLabel enemyLabel = new JLabel("Enemy");
mainFrame.add(enemyLabel);
moveEnemies(enemyLabel, mainFrame);
mainFrame.setLocationRelativeTo(null);
mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setVisible(true);
}
public void moveEnemies(JLabel label, JFrame frame)
{
SwingWorker<Void, Integer> enemyMover = new SwingWorker<Void, Integer>()
{
@Override
protected Void doInBackground() throws Exception
{
for (int i = 0; i <= 5; i++)
{
int x = 50 * i;
Thread.sleep(1000);
publish(x);
}
return null;
}
@Override
protected void process(List<Integer> chunks)
{
label.setSize(50, 50);
for(int num : chunks)
{
label.setText(String.valueOf(num));
label.setLocation(num, 250);
}
}
@Override
protected void done()
{
label.setText("Finished");
}
};
enemyMover.execute();
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(MainFrame::new);
}
}
I've also printed out the JLabel.getLocation()
and it prints the expected position, [250, 250] at the end of the loop, but the position doesn't change on the screen. I've also tried to revalidate()
, & repaint()
but neither seem to work.
You're fighting the frame's default layout manager (BorderLayout
) which would very much like to keep the label where it thinks it should be.
Take a look at Laying Out Components Within a Container
To "fix" the "immediate" problem, you "could" set the layout manager for the frame to null
, but this will open a can of very vicious and nasty worms. A better solution would be to stop using components in this way and use custom painting to render the text within a component.
Take a look at Painting in AWT and Swing, Performing Custom Painting and 2D Graphics for more details.
While it's possible to do some interesting animation with Swing components, there's a lot to take into consideration. If you're just creating a game of some kind, then it's better to use a custom painting based approach