Сделайте шаг назад первым. Существует критическая концепция, которую вы должны изучить и понять - разделение обязанностей.
Вам необходимо разделить и изолировать свою функциональность на отдельные классы, это упростит быструю и простую разработку повторяющейся функциональности.
Вам также следует сосредоточиться на отделении управления вашими «данными» от «пользовательского интерфейса», чтобы пользовательский интерфейс представлял ваши данные и использовался (где это применимо) для их обновления.
Исходя из вашего текущего дизайна, нет возможности «выбрать» панель истории сотрудников, поэтому бессмысленно использовать «общее» действие удаления - какой из них вы бы удалили? Вместо этого действие фактически относится к самой панели истории сотрудников, но ответственность за добавление и удаление этих компонентов полностью лежит на отдельном контроллере.
Давайте начнем с базовой концепции, сначала вам понадобятся некоторые данные ...
public class EmployeeHistory {
private String role;
private String duration;
private String employer;
public EmployeeHistory() {
}
public EmployeeHistory(String role, String duration, String employer) {
this.role = role;
this.duration = duration;
this.employer = employer;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getEmployer() {
return employer;
}
public void setEmployer(String employer) {
this.employer = employer;
}
}
Лично я предпочел бы interface
, возможный для «только для чтения» и для «чтения-записи», но мы будем придерживаться этого для краткости.
Далее нам нужен способ отобразить это ...
public class HistoryPane extends JPanel {
private final JTextField txtRole;
private final JTextField txtDuration;
private final JTextField txtEmployer;
private final JButton removeButton;
private EmployeeHistory history;
public HistoryPane(EmployeeHistory history) {
// This is what you should use when you want to populate
// the view or properties of the UI are changed
this.history = history;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lblRoleHeld = new JLabel("Role Held:");
add(lblRoleHeld, gbc);
gbc.gridx++;
txtRole = new JTextField();
txtRole.setText("role");
add(txtRole, gbc);
txtRole.setColumns(10);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblDuration = new JLabel("Duration:");
add(lblDuration, gbc);
gbc.gridx++;
txtDuration = new JTextField();
txtDuration.setText("duration");
add(txtDuration, gbc);
txtDuration.setColumns(10);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblEmployer = new JLabel("Employer:");
add(lblEmployer, gbc);
gbc.gridx++;
txtEmployer = new JTextField();
txtEmployer.setText("employer");
add(txtEmployer, gbc);
txtEmployer.setColumns(10);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
removeButton = new JButton("Remove");
add(removeButton, gbc);
}
public EmployeeHistory getHistory() {
return history;
}
public void addActionListener(ActionListener listener) {
removeButton.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
removeButton.removeActionListener(listener);
}
}
nb: Я не удосужился заполнить представление данными, я уверен, что вы можете получить его
Здесь следует отметить, что removeButton
на самом деле ничего не делает, ответственность делегируется какой-то другой стороне
Хорошо, мы можем удалить, но как мы можем добавить? Ну, для этого тебе нужен еще один компонент ...
public class ActionPane extends JPanel {
private JButton btn;
public ActionPane() {
setLayout(new GridBagLayout());
btn = new JButton("Add");
add(btn);
}
public void addActionListener(ActionListener listener) {
btn.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
btn.removeActionListener(listener);
}
}
Опять же, это на самом деле ничего не делает, просто делегирует ответственность кому-то еще.
nb: Это базовый пример, в равной степени вы можете передать какой-то контроллер, который будет выступать в качестве делегата, но результат в основном тот же
Хорошо, хорошо, но как это все работает? Ну, вам просто нужно соединить все функции вместе ...
Так что это возможная реализация функций добавления и удаления
ActionPane actionPane = new ActionPane();
actionPane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Layout constraints
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
// The actually history data
EmployeeHistory history = new EmployeeHistory();
// This is a model to manage the individual histories, making
// it easier to manage
histories.add(history);
// The history view...
HistoryPane pane = new HistoryPane(history);
// The remove action...
pane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Remove the action to improve the chances of been
// garbage collected
pane.removeActionListener(this);
// Remove the history from our model
histories.remove(pane.getHistory());
// Remove the view
contentPane.remove(pane);
contentPane.revalidate();
contentPane.repaint();
}
});
// Add the view (this is a little trick ;))
contentPane.add(pane, gbc, contentPane.getComponentCount() - 1);
contentPane.revalidate();
contentPane.repaint();
}
});
Пример выполнения
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JPanel contentPane;
private List<EmployeeHistory> histories;
public TestPane() {
histories = new ArrayList<>(25);
setLayout(new BorderLayout());
contentPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
contentPane.add(new JPanel(), gbc);
JScrollPane scrollPane = new JScrollPane(contentPane);
add(scrollPane);
ActionPane actionPane = new ActionPane();
actionPane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
EmployeeHistory history = new EmployeeHistory();
histories.add(history);
HistoryPane pane = new HistoryPane(history);
pane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pane.removeActionListener(this);
histories.remove(pane.getHistory());
contentPane.remove(pane);
contentPane.revalidate();
contentPane.repaint();
}
});
contentPane.add(pane, gbc, contentPane.getComponentCount() - 1);
contentPane.revalidate();
contentPane.repaint();
}
});
add(actionPane, BorderLayout.SOUTH);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class ActionPane extends JPanel {
private JButton btn;
public ActionPane() {
setLayout(new GridBagLayout());
btn = new JButton("Add");
add(btn);
}
public void addActionListener(ActionListener listener) {
btn.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
btn.removeActionListener(listener);
}
}
public class EmployeeHistory {
private String role;
private String duration;
private String employer;
public EmployeeHistory() {
}
public EmployeeHistory(String role, String duration, String employer) {
this.role = role;
this.duration = duration;
this.employer = employer;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getEmployer() {
return employer;
}
public void setEmployer(String employer) {
this.employer = employer;
}
}
public class HistoryPane extends JPanel {
private final JTextField txtRole;
private final JTextField txtDuration;
private final JTextField txtEmployer;
private final JButton removeButton;
private EmployeeHistory history;
public HistoryPane(EmployeeHistory history) {
// This is what you should use when you want to populate
// the view or properties of the UI are changed
this.history = history;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lblRoleHeld = new JLabel("Role Held:");
add(lblRoleHeld, gbc);
gbc.gridx++;
txtRole = new JTextField();
txtRole.setText("role");
add(txtRole, gbc);
txtRole.setColumns(10);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblDuration = new JLabel("Duration:");
add(lblDuration, gbc);
gbc.gridx++;
txtDuration = new JTextField();
txtDuration.setText("duration");
add(txtDuration, gbc);
txtDuration.setColumns(10);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblEmployer = new JLabel("Employer:");
add(lblEmployer, gbc);
gbc.gridx++;
txtEmployer = new JTextField();
txtEmployer.setText("employer");
add(txtEmployer, gbc);
txtEmployer.setColumns(10);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
removeButton = new JButton("Remove");
add(removeButton, gbc);
}
public EmployeeHistory getHistory() {
return history;
}
public void addActionListener(ActionListener listener) {
removeButton.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
removeButton.removeActionListener(listener);
}
}
}
Теперь, сказав все это, иди и прочитай Как использовать таблицы и Как использовать списки
Будет ли полезен массив?
Нет, не совсем. Это ограничит количество отображаемых элементов истории. Вместо этого я бы использовал ArrayList
для управления экземплярами объекта истории, как показано выше