Обычно достаточно вызова add
.
Примечание: BorderLayout
может содержать только один компонент в каждом местоположении.Поэтому, если вы добавите еще один компонент в местоположение NORTH
, ваша кнопка не будет видна.
Второе примечание: по умолчанию JPanel
не имеет BorderLayout
, а FlowLayout
.Вы установили BorderLayout
на этой конкретной панели?В противном случае ограничение BorderLayout#NORTH
является неправильным
Все вызовы validate
, revalidate
, repaint
могут быть удалены
Редактировать
Кажется, все-таки нужна какая-то проверка.У меня сложилось впечатление, что Swing должен быть достаточно умен, чтобы слушать событие, когда что-то добавляется в Container
, и обновлять все, что необходимо (немного похоже на обновление TableModel
, обновляет JTable
на основе событий,без необходимости вызывать repaint
или подобные сообщения на JTable
).
Однако, пробуя это в 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 );
}
} );
}
}