1

In NetBeans, I have used the GUI editor to make a JFrame and I've put a JPanel in the frame. At the moment, I'm trying to make a new button in the panel when the class constructs. This is the code I have, but I can't seem to get it to work. (The first line makes the button, the other lines try to show it.)

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

I've been googling all night, but can't seem to get it to work.

user1277170
  • 3,127
  • 3
  • 19
  • 19
  • 1) For better help sooner, post an [SSCCE](http://sscce.org/). 2) The [Nested Layout Example](http://stackoverflow.com/a/5630271/418556) dynamically adds labels. It is much the same principle. – Andrew Thompson Mar 27 '12 at 08:32
  • Your example code is a little sparse. Maybe you could create an example that is more complete? – Paaske Mar 27 '12 at 08:34

3 Answers3

3

Some times when you don't see a button it is a layout manager issue (as in you aren't setting the right properties for the layout manager). You can test this by disabling it:

this.jPanel2.setLayoutManager(null);

And setting bounds for the button (JButton.setBounds()).

If the above fixes your problem, then you need to look into the requirements set by the LayoutManager you are using (see also the answer by Robin).

All the calls to validate(), revalidate() and repaint() are not needed to do this.

Thirler
  • 20,239
  • 14
  • 63
  • 92
  • 2
    -1 for even suggesting null layout manager and manually setting the bounds. There is no valid reason in this case to do this – Robin Mar 27 '12 at 08:34
  • I suggested it to confirm it was a mistake in calling the layout manager, not as the solution. – Thirler Mar 27 '12 at 08:49
  • I added down-vote but removed it when I saw your comment. Perhaps an edit & expansion is called for. – Andrew Thompson Mar 27 '12 at 09:05
  • 1
    Agreed, added a line explaining the actual solution depends on the used layout manager. – Thirler Mar 27 '12 at 09:09
3

Normally the add call is sufficient.

Note: a BorderLayout can only contain one component in each location. So if you add another component in the NORTH location, your button will not be visible.

Second note: by default a JPanel does not have a BorderLayout but a FlowLayout. Have you set a BorderLayout on that specific panel ? Otherwise the BorderLayout#NORTH constraint is incorrect

All the validate,revalidate,repaint calls can be removed

Edit

It seems some sort of validation is needed after all. I was under the impression that Swing should be smart enough to listen for the event when something is added to a Container, and update whatever is necessary (a bit similar to updating a TableModel updates the JTable based on events, without the need to call repaint or the likes on the JTable).

However, when trying this in an SSCCE, I came to the following code (different versions, only post the most elaborate version)

  • without the scroll-pane, the validate calls seem to have no effect. I actually need to call pack again to make the new labels visible (not included in the SSCCE, but removing the scrollpane from the code is trivial)
  • with the scroll-pane, the validate call has an effect

    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 );
          }
        } );
    
      }
    
    }
    
Robin
  • 36,233
  • 5
  • 47
  • 99
  • I generally find it necessary to call `validate()` - as when adding labels in the example linked above. Can you provide an SSCCE that adds components dynamically and does not require it? – Andrew Thompson Mar 27 '12 at 09:07
  • I will give it a try tonight, but I do not remember ever needing it – Robin Mar 27 '12 at 09:58
  • Look forward to seeing the code. +1 for the comment on `BorderLayout.NORTH` – Andrew Thompson Mar 27 '12 at 10:07
  • 1
    @AndrewThompson I tried and I failed :-( . I even need to call `pack` when I do not use a scroll pane to make the new labels visible. With a scroll pane, the `validate` call is sufficient. Seems I was incorrect. Bright side, I learned something new today :-) – Robin Mar 27 '12 at 20:12
  • Cool. Hopefully that is now a 2nd person about these parts that knows it does not require `invalidate()`, `revalidate()` or `repaint()` (common misconceptions) but a single call to `validate()`. Start spreading the word. ;) – Andrew Thompson Mar 27 '12 at 21:29
  • @Robin for why reason is there `fLabelPanel.validate();` and with `fTestFrame.validate();` inside `JButton validateButton = new JButton( "Add + validate" );` are you OpenJDK user ??? – mKorbel Apr 19 '12 at 21:33
  • @mKorbel OS X user. And as described in the answer, I was experimenting with what calls were needed, and this was the result. Not yet sure why exactly those methods are needed – Robin Apr 19 '12 at 21:42
  • @Robin I'm using revalidate & repaint by default, to avoids reading the API, if required methods are correctly implemented ..., in most cases compiled code running on todays PC with good GPU, then there isn't important calculating with these two performance killers for java GUI – mKorbel Apr 19 '12 at 21:59
0

Create Dynamic JButton with Image and ActionListener - Java Swing

Create JButton dynamically with Image and the ActionListener . You will be able to change the button height , width horizontal gap and vertical gap in one place.

you can find more details from here

enter image description here

Community
  • 1
  • 1
Chathura Wijesinghe
  • 3,310
  • 3
  • 25
  • 41