【问题标题】:How to Dynamically Add JButton to JPanel?如何将 JButton 动态添加到 JPanel?
【发布时间】:2023-03-05 11:24:01
【问题描述】:

在 NetBeans 中,我使用 GUI 编辑器制作了一个 JFrame,并在框架中放置了一个 JPanel。 目前,我正在尝试在类构建时在面板中创建一个新按钮。 这是我拥有的代码,但我似乎无法让它工作。 (第一行是按钮,其他行尝试显示它。)

this.jPanel2.add(new JButton("Test"),BorderLayout.NORTH);
this.jPanel2.validate();
this.jPanel2.revalidate();
this.jPanel2.repaint();
this.jPanel2.setVisible(true);
this.revalidate();
this.setVisible(true);
this.repaint();

我整晚都在谷歌上搜索,但似乎无法正常工作。

【问题讨论】:

  • 1) 为了尽快获得更好的帮助,请发帖 SSCCE。 2) Nested Layout Example 动态添加标签。原理大致相同。
  • 您的示例代码有点稀疏。也许您可以创建一个更完整的示例?

标签: java swing


【解决方案1】:

有时当您看不到按钮时,这是布局管理器的问题(因为您没有为布局管理器设置正确的属性)。您可以通过禁用它来测试它:

this.jPanel2.setLayoutManager(null);

并为按钮设置边界 (JButton.setBounds())。

如果以上解决了您的问题,那么您需要查看您正在使用的 LayoutManager 设置的要求(另请参阅 Robin 的回答)。

不需要对validate()revalidate()repaint() 的所有调用。

【讨论】:

  • -1 甚至建议空布局管理器并手动设置边界。在这种情况下没有正当理由这样做
  • 我建议它确认调用布局管理器是一个错误,而不是作为解决方案。
  • 我添加了反对票,但在看到您的评论时将其删除。也许需要进行编辑和扩展。
  • 同意,添加了一行解释实际解决方案取决于使用的布局管理器。
【解决方案2】:

通常add 调用就足够了。

注意:BorderLayout 在每个位置只能包含一个组件。因此,如果您在 NORTH 位置添加另一个组件,您的按钮将不可见。

第二个注意事项:默认情况下,JPanel 没有BorderLayout,而是FlowLayout。您是否在该特定面板上设置了BorderLayout?否则BorderLayout#NORTH 约束不正确

可以删除所有validate,revalidate,repaint 调用

编辑

看来毕竟需要某种验证。我的印象是 Swing 应该足够聪明,可以在将某些内容添加到 Container 时监听事件,并更新任何必要的内容(有点类似于更新 TableModel 根据事件更新 JTable,无需致电repaintJTable 上的类似人员)。

但是,在 SSCCE 中尝试此操作时,我得到以下代码(不同版本,仅发布最复杂的版本)

  • 没有滚动窗格,validate 调用似乎没有效果。我实际上需要再次调用 pack 以使新标签可见(不包含在 SSCCE 中,但从代码中删除滚动窗格很简单)
  • 使用滚动窗格,validate 调用会产生效果

    import javax.swing.BoxLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import java.awt.BorderLayout;
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class AddLabelsAtRuntime {
    
      private int fLabelCounter = 0;
      private JPanel fLabelPanel;
      private final JFrame fTestFrame;
    
      public AddLabelsAtRuntime() {
        fLabelPanel = new JPanel(  );
        BoxLayout boxLayout = new BoxLayout( fLabelPanel, BoxLayout.PAGE_AXIS );
        fLabelPanel.setLayout( boxLayout );
        fTestFrame = new JFrame( "Dynamically add labels" );
      }
    
      private JFrame createUI(){
    
        Container contentPane = fTestFrame.getContentPane();
        contentPane.setLayout( new BorderLayout() );
    
        JScrollPane scrollPane = new JScrollPane( fLabelPanel );
        scrollPane.setPreferredSize( new Dimension( 200, 200 ) );
        contentPane.add( scrollPane, BorderLayout.CENTER );
    
        contentPane.add( createButtonPanel(), BorderLayout.SOUTH );
    
        fTestFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        fTestFrame.pack();
        return fTestFrame;
      }
    
      private void addLabel(){
        fLabelPanel.add( new JLabel( "Label " + ++fLabelCounter ) );
      }
    
      private JPanel createButtonPanel(){
        JPanel buttonPanel = new JPanel(  );
        BoxLayout boxLayout = new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS );
        buttonPanel.setLayout( boxLayout );
    
        JButton validateButton = new JButton( "Add + validate" );
        validateButton.addActionListener( new ActionListener() {
          @Override
          public void actionPerformed( ActionEvent e ) {
            addLabel();
            fLabelPanel.validate();
            fTestFrame.validate();
          }
        } );
        buttonPanel.add( validateButton );
    
        JButton noValidateButton = new JButton( "Add" );
        noValidateButton.addActionListener( new ActionListener() {
          @Override
          public void actionPerformed( ActionEvent e ) {
            addLabel();
          }
        } );
        buttonPanel.add( noValidateButton );
    
        JButton packButton = new JButton( "Add + pack" );
        packButton.addActionListener( new ActionListener() {
          @Override
          public void actionPerformed( ActionEvent e ) {
            addLabel();
            fTestFrame.pack();
          }
        } );
        buttonPanel.add( packButton );
    
        return buttonPanel;
      }
    
      public static void main( String[] args ) {
        EventQueue.invokeLater( new Runnable() {
          @Override
          public void run() {
            AddLabelsAtRuntime addLabelsAtRuntime = new AddLabelsAtRuntime();
            addLabelsAtRuntime.createUI().setVisible( true );
          }
        } );
    
      }
    
    }
    

【讨论】:

  • 我通常认为有必要调用validate() - 就像在上面链接的示例中添加标签时一样。能否提供动态添加组件且不需要的SSCCE?
  • 今晚我会试一试,但我不记得曾经需要它
  • 期待看到代码。 +1 评论BorderLayout.NORTH
  • @AndrewThompson 我试过但失败了:-(。当我不使用滚动窗格使新标签可见时,我什至需要调用pack。使用滚动窗格,@987654344 @电话就足够了。似乎我错了。好的一面,我今天学到了新东西:-)
  • 酷。希望现在是关于这些部分的第二个人知道它不需要invalidate()revalidate()repaint()(常见的误解),而是一次调用validate()。开始传播这个词。 ;)
【解决方案3】:

使用 Image 和 ActionListener 创建动态 JButton - Java Swing

使用 Image 和 ActionListener 动态创建 JButton。您将能够在一处更改按钮的高度、宽度水平间隙和垂直间隙。

you can find more details from here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2011-05-06
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多