使用 SwingWorker 移动组件

Moving Component With SwingWorker

我目前正在尝试使用 SwingWorker.JLabel 在屏幕上移动 我可以让 JLabel 更新 SwingWoker 中的文本但我不能让它改变它的位置。

这是我目前尝试过的方法

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

我还打印了 JLabel.getLocation() 并在循环结束时打印了预期位置 [250, 250],但屏幕上的位置没有改变。我也试过 revalidate(), & repaint() 但似乎都不起作用。

您正在与框架的默认布局管理器 (BorderLayout) 作斗争,它非常希望将标签保留在它认为应该的位置。

看看Laying Out Components Within a Container

对于"fix" "immediate" 问题,您"could" 将框架的布局管理器设置为null,但这将打开一个非常恶毒和令人讨厌的罐头蠕虫。更好的解决方案是停止以这种方式使用组件并使用自定义绘制来呈现组件内的文本。

查看 Painting in AWT and Swing, Performing Custom Painting and 2D Graphics 了解更多详情。

虽然可以使用 Swing 组件制作一些有趣的动画,但仍有许多因素需要考虑。如果您只是在创建某种游戏,那么最好使用基于自定义绘画的方法