Динамічне додавання і видалення компонентів з jpanel і jscrollpane, java swing і інша джава

Якщо трохи поміркувати з приводу того, як таке повинно відбуватися, відразу приходить на розум щось на кшталт: для додавання у JPanel (або куди там ще ми збираємося додати компонент) є метод add для додавання, значить для видалення повинен бути remove. Все вірно, все правильно - такі методи є і вони роблять саме те, що треба. Однак, є пара хитрощів, які потрібно знати, якщо хочеться зробити (або їсти не хочеться, але треба) динамічне додавання і видалення.

Подивимося код всього прикладу.

Звернемося відразу до тестового прикладу і погляньмо на заповітний код кнопок «Додати» і «Видалити». Що тут власне робиться. При додаванні нового JLabel робиться ось, що:

Для початку вираховуємо індекс, який буде у нового JLabel, щоб нумерація йшла по порядку. Далі створюємо новий JLabel, встановлюємо йому шрифт, вирівнювання і додаємо на панель. А тепер саме Цікаві - викликаємо метод revalidate у JScrollPane. Якщо не зробити цей виклик, то нічого ми не побачимо.

Подивимося, що відбувається при видаленні раніше доданого JLabel.

Для початку ми перевіряємо, чи є JLabel'и, які можуть бути видалені чи ні. Якщо такий JLabel є, то знаходимо його індекс (останній у списку), видаляємо його з панелі за допомогою виклику методу remove. Потім ми повинні викликати repaint у панелі JPanel, на якій розташовується JLabel. Виклик repaint говорить JPanel про те, що йому необхідно перемалювати. І нарешті, останній виклик - це revalidate у JScrollPane, на якій розташовується JPanel.

Таке ж можна зробити і без списку:

public class TestFrame extends JFrame

public static void createGUI () final JFrame frame = new JFrame ( «Test frame»);
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

final Font font = new Font ( «Verdana», Font.PLAIN, 25);

JPanel butPanel = new JPanel ();

JButton addButton = new JButton ( «+»);
addButton.setFont (font);
addButton.setFocusable (false);
butPanel.add (addButton);

JButton remButton = new JButton ( «-«);
remButton.setFont (font);
remButton.setFocusable (false);
butPanel.add (remButton);

final JPanel labPanel = new JPanel ();
final JScrollPane scrollPane = new JScrollPane (labPanel);
labPanel.setLayout (new BoxLayout (labPanel, BoxLayout.Y_AXIS));

addButton.addActionListener (new ActionListener () public void actionPerformed (ActionEvent e) int number = labPanel.getComponentCount () + 1;
JLabel label = new JLabel ( «Label» + number);
label.setAlignmentX (JLabel.CENTER_ALIGNMENT);
label.setFont (font);
labPanel.add (label);
scrollPane.revalidate ();
>
>);

remButton.addActionListener (new ActionListener () public void actionPerformed (ActionEvent e) if (labPanel.getComponentCount ()> 0) int index = labPanel.getComponentCount () - 1;
JLabel label = (JLabel) labPanel.getComponent (index);
labPanel.remove (label);
labPanel.repaint ();
scrollPane.revalidate ();
>
>
>);

frame.getContentPane (). setLayout (new BorderLayout ());
frame.getContentPane (). add (butPanel, BorderLayout.NORTH);
frame.getContentPane (). add (scrollPane, BorderLayout.CENTER);

frame.setPreferredSize (new Dimension (250, 200));
frame.pack ();
frame.setLocationRelativeTo (null);
frame.setVisible (true);
>

public static void main (String [] args) javax.swing.SwingUtilities.invokeLater (new Runnable () public void run () JFrame.setDefaultLookAndFeelDecorated (true);
createGUI ();
>
>);
>
>

Ем ... незрозуміле рішення.

Куди гнучкіше буде створити JList з власною моделлю (extends AbstractListModel), в якій всюди танцювати від власного private списку. У цьому списку, природно, можна зберігати не тільки порядковий номер і видаляти не тільки останній елемент.

А далі через ListCellRenderer виводити на екран що завгодно, причому щось складніше написи спорудити буде теж порівняно просто, тому що команду або фабрику компонентів зручно прив'язати до моделі списку.

Рішення гнучке, згоден. Але гнучкість слід використовувати, якщо в цьому є необхідність.

eto_ya:
Ем ... незрозуміле рішення.
Куди гнучкіше буде створити JList з власною моделлю (extends AbstractListModel), в якій всюди танцювати від власного private списку. У цьому списку, природно, можна зберігати не тільки порядковий номер і видаляти не тільки останній елемент.
А далі через ListCellRenderer виводити на екран що завгодно, причому щось складніше написи спорудити буде теж порівняно просто, тому що команду або фабрику компонентів зручно прив'язати до моделі списку.

Як в даному випадку додати ще один jLabel, що б він йшов паралельно першому?

Якщо я правильно зрозумів, то потрібно орієнтацію BoxLayout змінити з Y_AXIS на X_AXIS.
Тобто замість ось цього рядка
labPanel.setLayout (new BoxLayout (labPanel, BoxLayout.Y_AXIS));
буде ось така
labPanel.setLayout (new BoxLayout (labPanel, BoxLayout.X_AXIS));

bondforev а можеш ще розповісти як працювати з xml