Adicione dinamicamente componentes a um JDialog

Estou tendo problemas para adicionar JComponents a um JDialog quando o usuário clica em um botão no JDialog. Basicamente eu quero que seja assim:

Quando a caixa de diálogo é aberta

Então, quando o usuário clica em “Adicionar novo campo”, eu quero que seja assim:

Eu não consigo obter o diálogo para adicionar o novo JLabel ou JTextField. Alguém pode me apontar na direção certa?

EDIT : Esta é a ação para o botão “Add New Field” (apenas tentando um label agora).

@Action public void addNewField() { Container contentPane = getContentPane(); JLabel label = new JLabel ("welkom"); contentPane.add(label, BorderLayout.CENTER); } 

SOLUÇÃO :

Eu usei a solução da mre e fiz ela funcionar. Aqui está minha function final:

 @Action public void addNewField() { System.out.println("New Field..."); Container contentPane = getContentPane(); JLabel label = new JLabel ("welcome"); label.setBounds(10,10,100,10); //some random value that I know is in my dialog contentPane.add(label); contentPane.validate(); contentPane.repaint(); this.pack(); } 

Outro dos meus problemas é que estou usando um layout “Free Design” no NetBeans, o que significa que minha gravadora provavelmente estava em uma posição estranha em vez de estar dentro dos limites do meu diálogo (apenas um palpite). Eu resolvi esse problema com label.setBounds() para que ele mostrasse exatamente onde eu queria.

Ao adicionar / remover dinamicamente componentes de um contêiner, é necessário invocar revalidate() / validate() e repaint() posteriormente. O primeiro forçará o contêiner a planejar seus componentes novamente e o segundo removerá quaisquer “artefatos” visuais.

para evitar qualquer discusão adicional sobre os methods requeridos / não requeridos …

aviso: para adiciona / remove JComponents (simples estruturado apenas em uma linha / coluna e com o mesmo Size on Screen ) é suficiente apenas ação JFrame.pack() ,

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

mas para a GUI mais completa colocada por alguns dos Swing LayoutManagers padrão é necessário o uso de

 revalidate(); repaint(); // required in most of cases 

exemplo para uma coluna

 import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.LineBorder; public class AddComponentsAtRuntime { private JFrame f; private JPanel panel; private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack; public AddComponentsAtRuntime() { JButton b = new JButton(); b.setBackground(Color.red); b.setBorder(new LineBorder(Color.black, 2)); b.setPreferredSize(new Dimension(600, 10)); panel = new JPanel(new GridLayout(0, 1)); panel.add(b); f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(panel, "Center"); f.add(getCheckBoxPanel(), "South"); f.setLocation(200, 200); f.pack(); f.setVisible(true); } private JPanel getCheckBoxPanel() { checkValidate = new JCheckBox("validate"); checkValidate.setSelected(false); checkReValidate = new JCheckBox("revalidate"); checkReValidate.setSelected(false); checkRepaint = new JCheckBox("repaint"); checkRepaint.setSelected(false); checkPack = new JCheckBox("pack"); checkPack.setSelected(false); JButton addComp = new JButton("Add New One"); addComp.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JButton b = new JButton(); b.setBackground(Color.red); b.setBorder(new LineBorder(Color.black, 2)); b.setPreferredSize(new Dimension(600, 10)); panel.add(b); makeChange(); System.out.println(" Components Count after Adds :" + panel.getComponentCount()); } }); JButton removeComp = new JButton("Remove One"); removeComp.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int count = panel.getComponentCount(); if (count > 0) { panel.remove(0); } makeChange(); System.out.println(" Components Count after Removes :" + panel.getComponentCount()); } }); JPanel panel2 = new JPanel(); panel2.add(checkValidate); panel2.add(checkReValidate); panel2.add(checkRepaint); panel2.add(checkPack); panel2.add(addComp); panel2.add(removeComp); return panel2; } private void makeChange() { if (checkValidate.isSelected()) { panel.validate(); } if (checkReValidate.isSelected()) { panel.revalidate(); } if (checkRepaint.isSelected()) { panel.repaint(); } if (checkPack.isSelected()) { f.pack(); } } public static void main(String[] args) { AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime(); } } 

Eu concordo com o mre (1+ para a sua resposta), mas eu também gostaria de acrescentar que você pode precisar chamar o pack() no JDialog depois de adicionar ou remover componentes, especialmente se o diálogo precisar ser redimensionado para acomodar o componente como seu imagens indicam pode acontecer.

Editar 1
Por exemplo, com um JFrame (mas funciona da mesma forma com um JDialog):

 import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; public class SwingFoo extends JPanel { private JTextField nameField = new JTextField(10); private JComboBox searchTermsCombo = new JComboBox(); private JButton addNewFieldBtn = new JButton("Add New Field"); private JButton submitBtn = new JButton("Submit"); private JPanel centerPanel = new JPanel(new GridBagLayout()); private int gridY = 0; public SwingFoo() { GridBagConstraints gbc = createGBC(0, gridY); centerPanel.add(new JLabel("Name:"), gbc); gbc = createGBC(1, gridY); centerPanel.add(nameField, gbc); gridY++; gbc = createGBC(0, gridY); centerPanel.add(new JLabel("Search Terms:"), gbc); gbc = createGBC(1, gridY); centerPanel.add(searchTermsCombo, gbc); gridY++; addNewFieldBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { addNewFieldAction(e); } }); JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.PAGE_AXIS)); JPanel addNewFieldPanel = new JPanel(new GridLayout(1, 0)); addNewFieldPanel.add(addNewFieldBtn); addNewFieldPanel.add(new JLabel()); JPanel submitPanel = new JPanel(new BorderLayout()); submitPanel.add(submitBtn); bottomPanel.add(addNewFieldPanel); bottomPanel.add(Box.createVerticalStrut(5)); bottomPanel.add(submitPanel); int eb = 8; setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb)); setLayout(new BorderLayout()); add(centerPanel, BorderLayout.CENTER); add(bottomPanel, BorderLayout.SOUTH); } private void addNewFieldAction(ActionEvent e) { GridBagConstraints gbc = createGBC(0, gridY); centerPanel.add(new JLabel("New Item:"), gbc); gbc = createGBC(1, gridY); centerPanel.add(new JTextField(10), gbc); gridY++; Window win = SwingUtilities.getWindowAncestor(addNewFieldBtn); if (win != null) { win.pack(); win.setLocationRelativeTo(null); } } private GridBagConstraints createGBC(int x, int y) { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.anchor = (x == 0) ? gbc.LINE_START : gbc.LINE_END; gbc.fill = (x == 0) ? gbc.BOTH : gbc.HORIZONTAL; gbc.insets = (x == 0) ? new Insets(5, 0, 5, 5) : new Insets(5, 5, 5, 0); return gbc; } private static void createAndShowGui() { JFrame frame = new JFrame("SwingFoo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new SwingFoo()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } }