重新排序标签

Reordering labels

我正在从 FlowLayout JPanel 中的数组动态创建标签,并将它们存储在 JLabel 数组中以供将来参考。它们按预期从左到右显示。
我想将其中一个标签移动到面板的开头(最左边)。

我不介意整个数组移动或只是两个标签交换位置:

apple orange pear cherry melon
              |
cherry apple orange pear melon
              or
cherry orange pear apple melon

我已经交换了数组条目,然后是 revalidate() 和 repaint(),但没有任何反应。
有没有一种简单的方法可以移动 swing 组件,而无需删除所有组件,然后将它们重新添加到面板或将所有属性从一个标签复制到另一个标签(我定义了其他标签,而不仅仅是文本)?

这是我的代码的精简版:

import javax.swing.*;

public class Test extends JPanel {
    public Test () {
        String entries[] = { "apple", "orange", "pear", "cherry", "melon" };
        JLabel[] lbls = new JLabel[entries.length];

        for (int i = 0; i < entries.length; ++i) {
            lbls[i] = new JLabel();
            lbls[i].setText(entries[i]);
            add(lbls[i]);
        }

        // swap array entries
        JLabel tmplbl = new JLabel();
        tmplbl = lbls[3];
        lbls[3] = lbls[0];
        lbls[0] = tmplbl;
        revalidate();
        repaint();

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.setContentPane(new Test());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
                frame.pack();
            }
        });
    }
}

在修复您的错误之前,有几件事需要修复:

  1. 此行有 2 个错误:public class Test extends JPanel {

    • Class名字,你知道有多少人叫他们类Test吗?很多!使其更具描述性,例如 SwapLabelsTest
    • extends JPanel,您没有更改 JPanel 的行为,因此在这种情况下无需扩展它,只需创建 JPanel.[= 的新实例即可58=]
  2. 不要把所有东西都放在构造函数中,最好有一个initialize()方法或类似的东西(下面代码中的createAndShowGUI())来处理GUI建设。这似乎是最简单的方法,但是当项目变大时,分离这部分会派上用场。

  3. 将您的变量移动到更大的范围,以便于处理,除非这些变量是方法的本地变量,否则这将提高性能和可读性。

  4. 包括一个检测事件的组件,例如 JButton,以便在触发该事件(单击按钮)时执行交换。

  5. 你的交换逻辑似乎有点奇怪,你在那里创建了新的 JLabels 并试图交换它们,但最好在这里有一种 MVC 模式,所以您交换数组中的值,然后在进行这些更改后更新 UI。

    您可能会问,但我该怎么做呢?像这样:

    String tmpString = entries[3];
    entries[3] = entries[1];
    entries[1] = tmpString;
    

    上面的代码交换了条目数组中的值,我们现在要做的就是在 for-loop.

    中用 lbl[i].setText(entries[i]) 更新每个 label

所以,你最终会得到这样的结果:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {
    private JFrame frame;
    private JPanel panel;
    private String entries[] = { "apple", "orange", "pear", "cherry", "melon" };
    private JLabel[] lbls = new JLabel[entries.length];
    JButton button;

    private void createAndShowGUI() {
        panel = new JPanel();

        for (int i = 0; i < entries.length; ++i) {
            lbls[i] = new JLabel();
            lbls[i].setText(entries[i]);
            panel.add(lbls[i]);
        }

        button = new JButton("Swap 1 and 3");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String tmpString = entries[3];
                entries[3] = entries[1];
                entries[1] = tmpString;
                reloadLabels();
            }
        });

        frame = new JFrame("Test");
        frame.add(panel);
        frame.add(button, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.pack();
    }

    private void reloadLabels() {
        for (int i = 0; i < entries.length; ++i) {
            lbls[i].setText(entries[i]);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test().createAndShowGUI();
            }
        });
    }
}

每次单击按钮时,项目 1 和 3(索引)将被交换并且 UI 将被更新(因为 .setText 触发 UI 更新)。

I've swapped array entries

交换数组中的条目没有任何作用。数组与面板无关

所以你需要调整面板上的组件。

I want to move one of the labels to the beginning (leftmost) of the panel.

嗯,这与 "swapping" 的要求不同。也比较容易。

您可以将组件添加到面板并指定其在面板中的位置,因此将组件添加到开头很容易,因为它的位置始终为零。

所以要将第 3 个组件移到开头,代码将类似于:

Component component = panel.getComponent(2);
panel.add(component, 0);
panel.revalidate();
panel.repaint();

如果你真的想要交换,那么代码会类似。您将在两个位置都获得组件,然后先将一个组件添加回较低位置,然后将另一个组件添加回较高位置。