无法在方法中使用 html 创建新的 JLabel

unable to create new JLabel with html in method

我正在尝试在 Java 中制作固定宽度的标签,我找到了一个解决方案 here。 但是每当我将任何内容放入标签中时,我都会失败——而标签是在方法中创建的。

我的代码在这里:

public class testingGui

    JFrame myframe      = new JFrame("Some title here");
    Container pane_ctn  = myframe.getContentPane();

    public static void main(String[] args){
        testingGui gui = new testingGui();
        gui.init();
    }

    private void init(){

        myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myframe.setSize(320, 480);
        myframe.setVisible(true);
        pane_ctn.setLayout(new BoxLayout(pane_ctn, BoxLayout.PAGE_AXIS));

        JLabel lable = new JLabel("<html>Java is a general-purpose computer programming language</html>");  
        pane_ctn.add(lable);

    }

}

JLabel lable = new JLabel("<html>Java is a general-purpose computer programming language</html>"); 永远不会 运行。 (并使 pane_ctn 变为空白,即使添加了其他 UI 元素)

但是我发现在将标签创建为字段时它可以工作,如下所示:

public class testingGui {

    JFrame myframe      = new JFrame("Some title here");
    Container pane_ctn  = myframe.getContentPane();
    JLabel lable = new JLabel("<html>Java is a general-purpose computer programming language</html>");  

    // I just cut the whole line and paste here, nothing else has changed.
    /* ...  */
}

所以这是我的问题: 在方法调用中使用 html 创建标签的正确方法是什么?我需要即时创建它。谢谢。


编辑:

谢谢ybanen给我一个很好的答案,还有其他帮助者。

现在我可以创建看起来不错的标签了。

出现这种情况是因为您在显示后尝试修改 GUI。在您的情况下,最好是创建整个 GUI,然后显示框架:

public class TestingGui {

    public static void main(final String[] args) {
        final JLabel label = new JLabel("<html>Java is a general-purpose computer programming language</html>");

        final JFrame frame = new JFrame("Test");
        final Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.PAGE_AXIS));
        frame.getContentPane().add(label);
        frame.setSize(320, 480);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

但是,如果你真的需要在GUI显示后添加标签,你必须遵循几个规则:

  1. GUI 的任何修改都必须在事件调度线程 (EDT) 中完成。
  2. 容器显示后,即已布局。所以如果你想在里面添加一个新的组件,你必须强制布局它的内容(使用 revalidate() 然后 repaint())。

I need it created on the fly.

为什么?或者更确切地说,为什么不在启动时创建和添加标签,然后在需要时设置文本呢?

My example is a To-Do list, I have a array to store the data, the label is create inside a for loop.

使用 JList!

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class EditableList {

    private JComponent ui = null;

    String[] items = {
        "Do 100 push ups.",
        "Buy a book.",
        "Find a cat.",
        "Java is a general purpose computer language that is concurrent, "
            + "class based, object oriented and specifically designed to have "
            + "as few implementation dependencies as possible.",
        "Conquer the world."
    };

    EditableList() {
        initUI();
    }

    public void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        JList<String> list = new JList<String>(items);
        list.setCellRenderer(new ToDoListRenderer());
        list.getSelectionModel().setSelectionMode(
                ListSelectionModel.SINGLE_SELECTION);
        ui.add(new JScrollPane(list));

        JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER));
        controls.add(new JButton("Edit Selected"));
        controls.add(new JButton("Delete Selected"));

        ui.add(controls, BorderLayout.PAGE_END);
    }

    class ToDoListRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(
                JList<? extends Object> list, 
                Object value, 
                int index, 
                boolean isSelected, 
                boolean cellHasFocus) {
            Component c = super.getListCellRendererComponent(
                    list, value, index, isSelected, cellHasFocus);
            JLabel l = (JLabel)c;
            l.setText("<HTML><body style='width: 250px;'>" + value.toString());

            return l;
        }

    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(
                            UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {
                }
                EditableList o = new EditableList();

                JFrame f = new JFrame("To Do List");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}