Dynamically Add Components to a JDialog

2018-12-31 14:44发布

问题:

I am having trouble adding JComponents to a JDialog when the user clicks a button on the JDialog. Basically I want it to look like this:

\"When

Then, when the user clicks \"Add New Field\" I want it to look like this:

\"After

I cannot seem to get the dialog to add the new JLabel or JTextField. Can anyone point me in the right direction?

EDIT: This is the action for the \"Add New Field\" button (Just trying a label now).

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

SOLUTION:

I used mre\'s solution and got it to work. Here is my final function:

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

Another one of my problems is that I am using a \"Free Design\" layout in NetBeans, which meant that my label was probably in some weird position rather than being in the bounds of my dialog (just a guess). I solved this problem with label.setBounds() so that it showed exactly where I wanted it to.

回答1:

When dynamically adding/removing components from a container, it\'s necessary to invoke revalidate()/validate() and repaint() afterward. The former will force the container to layout its components again and the latter will remove any visual \"artifacts\".



回答2:

to avoiding any further discusion about required/non-required any of Methods ...

notice: for adds/removes JComponents (simple structured just in one Row/Column and with same Size on Screen) is sufficient just action JFrame.pack(),

\"enter

\"enter

\"enter

but for most complete GUI layed by some of standard Swing LayoutManagers is required usage of

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

example for one Column

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


回答3:

I agree with mre (1+ to his answer), but I would also like to add that you may need to call pack() on the JDialog after adding or removing components especially if the dialog will need to resize to accomodate the component as your images indicate may happen.

Edit 1
For example with a JFrame (but it works the same with a 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();
         }
      });
   }
}