如何将 JLabels 动态添加到 JPanel?

Posted

技术标签:

【中文标题】如何将 JLabels 动态添加到 JPanel?【英文标题】:How to dynamically add JLabels to JPanel? 【发布时间】:2012-12-11 09:27:20 【问题描述】:

我遇到了这个问题。我有一个 JPanel,通常我会像这样创建一个 JLabel:

JLabel lblNewLabel = new JLabel("New label");
lblNewLabel.setBounds(0, 0, 135, 14);
panel.add(lblNewLabel);

但我希望每次单击按钮时,在该面板中创建一个大小相同但高度位置不同的新 JLabel。我试过了:

panel.add(new JLabel(stringName));

但这样我就无法设置它的界限。我从 JTextField 获得的字符串名称。

【问题讨论】:

"通常我会像这样创建一个 JLabel:..lblNewLabel.setBounds(0, 0, 135, 14);" 通常你做错了。 使用布局! 【参考方案1】:

尝试交换命令的顺序,先添加面板,然后设置位置。

【讨论】:

【参考方案2】:

首先,使用layout。正确完成布局将按照您的意愿放置组件。其次,在将组件动态添加到布局时,您需要告诉布局进行更新。这是一个例子,每次按下按钮时都会添加一个标签:

public static void main(String[] args) 

    final JFrame frame = new JFrame("Test");
    frame.setLayout(new GridLayout(0, 1));

    frame.add(new JButton(new AbstractAction("Click to add") 
        @Override
        public void actionPerformed(ActionEvent e) 

            SwingUtilities.invokeLater(new Runnable() 
                @Override
                public void run() 
                    frame.add(new JLabel("Bla"));
                    frame.validate();
                    frame.repaint();
                
            );
        
    ));

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    SwingUtilities.invokeLater(new Runnable() 
        @Override public void run() 
            frame.setVisible(true);
        
    );

【讨论】:

Swing 组件也应该在 EDT 上创建,setSize 是真正的不可用,正确的LayoutManager 并在设置为可见之前在JFrame 上调用pack() @DavidKroukamp:在实现之前无需在 EDT 上执行(在本例中为 setVisible(true)),并且关于 pack() 这个示例需要更多空间来证明这一点。 我不明白你的意思?我没有看到 invokeLater 块会导致 JFrame#setVisible(true); 在 EDT 上运行?至于pack()在添加组件以调整JFrame大小后会派上用场的空间,如果setSize是必须的,而必须覆盖getPrefferedSize()并返回适当的尺寸【参考方案3】:

正如@AndrewThompson 所说,使用正确的LayoutManager,您不应该乱用setBounds 等。

这是我做的一个例子(每次点击JButton 时,只需在JPanel 中添加一个JLabel):

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class Test 

    public Test() 
        createAndShowUI();
    

    private void createAndShowUI() 
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initComponents(frame);

        frame.setResizable(false);
        frame.pack();
        frame.setVisible(true);
    

    private void initComponents(final JFrame frame) 

        final JPanel panel = new JPanel();

        JButton button = new JButton("Add label");

        button.addActionListener(new ActionListener() 
            int count = 1;

            @Override
            public void actionPerformed(ActionEvent e) 
                JLabel _lbl = new JLabel("Label " + count);//make label and assign text in 1 line

                panel.add(_lbl);//add label we made

                panel.revalidate();
                panel.repaint();

                frame.pack();//so our frame resizes to compensate for new components

                count++;
            
        );

        frame.add(panel, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);
    

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

【讨论】:

以上是关于如何将 JLabels 动态添加到 JPanel?的主要内容,如果未能解决你的问题,请参考以下文章

如何在已动态添加的JLabel的JPanel中getLocation()?

如何强制刷新/重绘 JScrollPane?

如何将视觉添加到 JComponent

如何将两个 JPanel 添加到中心的 JFrame?

跨面板对齐 Swing 组件

如何将自定义的 MouseMotionListener 添加到 JPanel?