Опять же, я настоятельно призываю вас отделить модель от вида. Модель должна храниться в виде чистых данных, должна рассматриваться многими различными способами, если это необходимо, и поэтому не должна быть так тесно связана с представлением.
Итак, предполагая схожие данные, ...
String[][] data = {
{ "1", "Steve", "AUS" },
{ "2", "Virat", "IND" },
{ "3", "Kane", "NZ" },
{ "4", "David", "AUS" },
{ "5", "Ben", "ENG" },
{ "6", "Eion", "ENG" } };
давайте создадим лучшую модель
Давайте создадим класс для хранения данных на 1 строку:
public class RowData {
private int id;
private String name;
private String countryCode;
public RowData(int id, String name, String countryCode) {
super();
this.id = id;
this.name = name;
this.countryCode = countryCode;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
@Override
public String toString() {
return "RowData [id=" + id + ", name=" + name + ", countryCode=" + countryCode + "]";
}
}
А затем используйте это для создания модели таблицы. Я расширил DefaultTableModel и сохранил данные одной строки как одну строку в модели. На самом деле это одномерный набор данных:
@SuppressWarnings("serial")
class MyTableModel extends DefaultTableModel {
private static final Object[] COLUMN_NAMES = new Object[] { "ODI Rankings" };
public MyTableModel() {
super(COLUMN_NAMES, 0);
}
public void addRow(RowData rowData) {
super.addRow(new Object[] { rowData });
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex != 0) {
String text = "for column index: " + columnIndex;
throw new IllegalArgumentException(text);
} else {
return RowData.class;
}
}
}
Теперь ключом к вашей проблеме является создание рендерера и редактора, который будет отображать данные в JPanel, который содержит 3 JTextFields (как это выглядит по вашему желанию), поэтому работающий рендерер может быть:
@SuppressWarnings("serial")
class MyCellRenderer extends JPanel implements TableCellRenderer {
private JTextField idField = new JTextField(10);
private JTextField nameField = new JTextField(10);
private JTextField countryCodeField = new JTextField(10);
public MyCellRenderer() {
add(idField);
add(nameField);
add(countryCodeField);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
RowData rowData = (RowData) value;
if (rowData != null) {
idField.setText("" + rowData.getId());
nameField.setText(rowData.getName());
countryCodeField.setText(rowData.getCountryCode());
} else {
idField.setText("");
nameField.setText("");
countryCodeField.setText("");
}
if (isSelected) {
this.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
} else {
this.setBorder(BorderFactory.createLineBorder(Color.black, 1));
}
return this;
}
}
и редактор (который строится из редактора ячеек по умолчанию):
@SuppressWarnings("serial")
class MyCellEditor extends AbstractCellEditor implements TableCellEditor {
private JPanel mainPanel = new JPanel();
private JTextField idField = new JTextField(10);
private JTextField nameField = new JTextField(10);
private JTextField countryCodeField = new JTextField(10);
private RowData currentData;
public MyCellEditor() {
mainPanel.add(idField);
mainPanel.add(nameField);
mainPanel.add(countryCodeField);
}
@Override
public Object getCellEditorValue() {
int id = 0;
try {
id = Integer.parseInt(idField.getText());
} catch (NumberFormatException nfe) {
return currentData;
// warn user here
}
String name = nameField.getText();
String countryCode = countryCodeField.getText();
RowData rowData = new RowData(id, name, countryCode);
return rowData;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
currentData = (RowData) value;
if (currentData != null) {
idField.setText("" + currentData.getId());
nameField.setText(currentData.getName());
countryCodeField.setText(currentData.getCountryCode());
}
return mainPanel;
}
}
Оставшийся управляющий код с импортом, а также класс, расширяющий JTable для решения проблемы высоты строки:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
@SuppressWarnings("serial")
public class JTableWithJPanelExample2 extends JPanel {
private MyTableModel tableModel = new MyTableModel();
private MyTable table = new MyTable(tableModel);
public JTableWithJPanelExample2() {
MyCellRenderer rendererEditor = new MyCellRenderer();
table.setDefaultRenderer(RowData.class, rendererEditor);
table.setDefaultEditor(RowData.class, new MyCellEditor());
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "ODI Rankings",
TitledBorder.CENTER, TitledBorder.TOP));
setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
public void addRow(RowData rowData) {
tableModel.addRow(rowData);
}
public static void main(String[] args) {
String[][] data = {
{ "1", "Steve", "AUS" },
{ "2", "Virat", "IND" },
{ "3", "Kane", "NZ" },
{ "4", "David", "AUS" },
{ "5", "Ben", "ENG" },
{ "6", "Eion", "ENG" } };
JTableWithJPanelExample2 example = new JTableWithJPanelExample2();
for (String[] datum : data) {
int id = Integer.parseInt(datum[0]);
String name = datum[1];
String countryCode = datum[2];
RowData rowData = new RowData(id, name, countryCode);
example.addRow(rowData);
}
JFrame gui = new JFrame("GUI");
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.add(example);
gui.pack();
gui.setLocationRelativeTo(null);
gui.setVisible(true);
}
}
@SuppressWarnings("serial")
class MyTable extends JTable {
public MyTable(MyTableModel tableModel) {
super(tableModel);
}
// a kludge to make the cells high enough to display properly
@Override
public int getRowHeight() {
return 2 * super.getRowHeight();
}
}
Я бы предположил, что GUI в конечном итоге будет привязан к базе данных, и используя более чистая модель сделает это намного проще, чище и безопаснее, включая передачу данных из базы данных в модель и из модели в базу данных. Опять же, это просто имеет смысл.