Динамически добавлять компоненты в JDialog
у меня возникли проблемы с добавлением JComponents в JDialog, когда пользователь нажимает кнопку на JDialog. В основном я хочу, чтобы это выглядело так:
затем, когда пользователь нажимает "добавить новое поле", я хочу, чтобы оно выглядело так:
Я не могу заставить диалоговое окно добавить новый JLabel или JTextField. Кто-нибудь может указать мне правильное направление?
редактировать: это действие для "Добавить новый Кнопка "поле" (просто попробуйте метку сейчас).
@Action
public void addNewField()
{
Container contentPane = getContentPane();
JLabel label = new JLabel ("welkom");
contentPane.add(label, BorderLayout.CENTER);
}
решение:
я использовал решение mre и заставил его работать. Вот моя конечная функция:
@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();
}
еще одна из моих проблем заключается в том, что я использую макет "свободного дизайна" в NetBeans, что означало, что моя метка, вероятно, находилась в каком-то странном положении, а не в пределах моего диалога (просто догадка). Я решил эту проблему с помощью label.setBounds()
так, чтобы он показал, где именно я хотел к.
3 ответов
при динамическом добавлении/удалении компонентов из контейнера, необходимо вызвать revalidate()
/validate()
и repaint()
позже. Первый заставит контейнер снова компоновать свои компоненты, а последний удалит любые визуальные "артефакты".
чтобы избежать каких-либо дальнейших рассуждений о требуемых/не требуемых методах ...
примечание: для добавляет/удаляет JComponents
(простой структурированный только в одной строке / столбце и с тем же Size on Screen
) достаточно просто действий JFrame.pack()
,
но для наиболее полного GUI заложены некоторые из стандартных Swing LayoutManagers
требуется использование
revalidate();
repaint(); // required in most of cases
пример для одного столбца
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();
}
}
Я согласен с mre (1+ к его ответу), но я также хотел бы добавить, что вам может потребоваться позвонить pack()
на JDialog после добавления или удаления компонентов, особенно если диалоговое окно нужно будет изменить размер, чтобы разместить компонент, как ваши изображения указывают может произойти.
изменить 1
Например, с JFrame (но он работает так же с 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();
}
});
}
}