Reputation: 3227
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.
Upvotes: 1
Views: 5926
Reputation: 3349
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
Upvotes: 0
Reputation: 36601
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)
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 );
}
} );
}
}
Upvotes: 3
Reputation: 20760
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.
Upvotes: 3