Good day!
There is a problem in downloaded program. You can copy a row by clicking on it by right mouse button, but after that when you change data in one cell data will be changed in every cell in column. Please, help me to understand, what I've missed.
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
public class Main extends JFrame{
JMenuItem obrc;
JTable table;
DataModel tm;
JScrollPane scrollTable;
Main() {
super("Example JTable");
Container c = getContentPane();
ArrayList<String> columnNames = new ArrayList<String>();
columnNames.add("Type"); columnNames.add("Sort"); columnNames.add("Thickness"); columnNames.add("Width");
tm = new DataModel(columnNames);
table = new JTable(tm);
c.add(new JScrollPane(table), BorderLayout.CENTER);
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
table.getColumnModel().getColumn(0).setPreferredWidth(40);
table.getColumnModel().getColumn(1).setPreferredWidth(40);
table.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent event) {
if (SwingUtilities.isRightMouseButton(event)) {
JPopupMenu obrcd = new JPopupMenu();
obrc = new JMenuItem("Copy");
obrc.addActionListener(new MenuListener());
obrcd.add(obrc);
obrcd.show(c, event.getX(), event.getY());
}
}
});
}
public class MenuListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
int[] nums = table.getSelectedRows();
if (nums.length != 0) {
if (e.getSource() == obrc) {
ArrayList<Object[]> list = tm.getRows(nums);
tm.addRows(list);
}
else JOptionPane.showMessageDialog(null,
"Select at least one row", "Warning", JOptionPane.ERROR_MESSAGE);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main();
}
});
}
class DataModel extends AbstractTableModel{
ArrayList<Object[]> data = new ArrayList<Object[]>();
ArrayList<String> columnNames = new ArrayList<String>();
public DataModel(ArrayList<String> cNames){
super();
columnNames = cNames;
Object[] dat = new Object[4];
dat[0] = "board";
dat[1] = "1";
dat[2] = "25";
dat[3] = "150";
data.add(dat);
}
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return true;
}
public Object getValueAt(int rowIndex, int columnIndex){
Object[] row = data.get(rowIndex);
return row[columnIndex];
};
public void setValueAt(Object newValue, int rowIndex, int columnIndex){
data.get(rowIndex)[columnIndex] = newValue;
fireTableDataChanged();
}
public int getRowCount()
{
return data.size();
};
public int getColumnCount()
{
return columnNames.size();
};
public String getColumnName(int column)
{
return columnNames.get(column);
}
public ArrayList<Object[]> getRows(int[] nums) {
ArrayList<Object[]> newdata = new ArrayList<Object[]>();
for (int i = 0; i < nums.length; i++) {
newdata.add(data.get(nums[i]));
}
return newdata;
}
public void addRows (ArrayList<Object[]> rows) {
for (int i = 0; i < rows.size(); i++) data.add(rows.get(i));
fireTableDataChanged();
}
}
}
Problem when you are adding new rows
public void addRows (ArrayList<Object[]> rows) {
for (int i = 0; i < rows.size(); i++) data.add(rows.get(i));
fireTableDataChanged();
}
Your copied row(s) will point to same object(s) with selected row(s). You need clone to new object:
public void addRows (ArrayList<Object[]> rows) {
for (int i = 0; i < rows.size(); i++) {
Object[] clone = rows.get(i).clone();
data.add(clone);
}
fireTableDataChanged();
}
Related
I have a problem in my code that when using cell edit not allowed then the column size does not work properly
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.table.DefaultTableModel;
import javax.swing.ListSelectionModel;
public class cTable extends JPanel {
private final int keyIndex;
private final int keyIncrement;
private ArrayList<String> tHeaderTitle;
private ArrayList<Integer> tHeaderWidth;
DefaultTableModel dataModel = new DefaultTableModel() {
#Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
return false;
}
};
JTable table = new JTable(dataModel);
public cTable(ArrayList<String> THeaderTitle, ArrayList< Integer> THeaderWidth, int KeyIndex, int KeyIncrement) {
if (THeaderTitle.isEmpty()) {
tHeaderTitle.add("Title1");
} else {
tHeaderTitle = new ArrayList<>(THeaderTitle);
}
if (THeaderWidth.isEmpty()) {
tHeaderWidth.add(30);
} else {
tHeaderWidth = new ArrayList<>(THeaderWidth);
}
keyIndex = KeyIndex;
keyIncrement = KeyIncrement;
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setAutoscrolls(true);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setAutoscrolls(true);
for (int i = 0; i < tHeaderTitle.size(); i++) {
dataModel.addColumn(tHeaderTitle.get(i));
table.getColumnModel().getColumn(i).setPreferredWidth(tHeaderWidth.get(i));
}
table.setPreferredScrollableViewportSize(new Dimension(TotalWidth(tHeaderWidth) + 110, 100));
table.getTableHeader().setResizingAllowed(false);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowHeight(25);
add(scrollPane);
}
public void addColumn(String cName, int cWidth) {
dataModel.addColumn(cName);
table.getColumnModel().getColumn(dataModel.getColumnCount() - 1).setPreferredWidth(cWidth);
table.setPreferredScrollableViewportSize(new Dimension(TotalWidth(tHeaderWidth) + cWidth, 150));
tHeaderWidth.add(cWidth);
}
public void addRow(String[] values) {
boolean exists = false;
if (dataModel.getRowCount() == 0) {
dataModel.addRow(values);
} else {
for (int i = 0; i < dataModel.getRowCount(); i++) {
if (dataModel.getValueAt(i, keyIndex) == values[keyIndex]) {
dataModel.setValueAt(Integer.valueOf(String.valueOf(dataModel.getValueAt(i, keyIncrement))) + 1, i, keyIncrement);
exists = true;
}
}
if (!exists) {
dataModel.addRow(values);
}
}
}
private int TotalWidth(ArrayList<Integer> wl) {
int sum = 0;
for (Integer wl1 : wl) {
sum += wl1;
}
return sum;
}
}
and in my main frame class mainClass I used the cTable component to create my customized table but the column size does not appear to be right , actually it does not work and the cells should be editable
import javax.swing.JPanel;
........
public class mainClass {
public static void main(String args[]) {
......
// initialize frame settings to add a cTable component
......
ArrayList<Integer> TheaderWidth = new ArrayList<>();
ArrayList<String> TheaderTitle = new ArrayList<>();
cTable InvTable;
TheaderTitle.add("id");
TheaderTitle.add("Qty");
TheaderTitle.add("Description");
TheaderTitle.add("Notes");
TheaderWidth.add(30);
TheaderWidth.add(50);
TheaderWidth.add(200);
TheaderWidth.add(100);
InvTable = new cTable(TheaderTitle, TheaderWidth, 1, 2);
InvTable.setBounds(10, 10, 600, 300);
panel1.add(InvTable);
InvTable.setVisible(true);
this.pack();
}
}
I have the following "sample" code almost, but the column names dissapiared after ~2 hours codeing and i cant find where.
Can somebody tell me why the datamodel doesnt add the column names to the JTable?
My code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
class MyTableModel extends JPanel {
private static final int CHECK_COL = 3;
private static Object[][] DATA = {
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false},
{"","","",false},{"","","",false},{"","","",false},{"","","",false}
};
public static String[] COLUMNS = {"Debtid","Nev","VHO", "Check"};
protected DataModel dataModel = new DataModel(DATA, COLUMNS);
private JTable table = new JTable(dataModel);
private DefaultListSelectionModel selectionModel;
public MyTableModel(){
super(new BorderLayout());
this.add(table);
this.add(new ControlPanel(), BorderLayout.SOUTH);
table.setPreferredScrollableViewportSize(new Dimension(250, 175));
selectionModel = (DefaultListSelectionModel) table.getSelectionModel();
}
private class DataModel extends DefaultTableModel {
public DataModel(Object[][] data, Object[] COLUMNS) {
super(data, COLUMNS);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == CHECK_COL) {
return getValueAt(0, CHECK_COL).getClass();
}
return super.getColumnClass(columnIndex);
}
#Override
public boolean isCellEditable(int row, int column) {
return true;
}
}
private class ControlPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = -7342459414751761853L;
public ControlPanel() {
this.add(new JLabel("Selection:"));
this.add(new JButton(new SelectionAction("Clear", false)));
this.add(new JButton(new SelectionAction("Check", true)));
}
}
private class SelectionAction extends AbstractAction {
boolean value;
public SelectionAction(String name, boolean value) {
super(name);
this.value = value;
}
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < dataModel.getRowCount(); i++) {
if (selectionModel.isSelectedIndex(i)) {
dataModel.setValueAt(value, i, CHECK_COL);
}
}
}
}
public void setValueAt_Cell(String val, int row, int col) {
// TODO Auto-generated method stub
if(row==DATA.length){
DATA=cloneArray(DATA);
}
dataModel.setValueAt(val, row, col);
}
public static Object[][] cloneArray(Object[][] src) {
int length = src.length;
Object[][] target = new Object[length+1][src[0].length];
for (int i = 0; i < length; i++) {
System.arraycopy(src[i], 0, target[i], 0, src[i].length);
}
target[length] = new Object[]{"","","",false};
return target;
}
public String getValAtPos(int row,int col) {
//System.out.println(dataModel.getValueAt(row, col));
return dataModel.getValueAt(row, col).toString();
}
public int getRowCount(){
return DATA.length;
}
}
You need to wrap JTable with JScrollPane : this.add(new JScrollPane(table));.
Good day, guys. I would just like to ask, how can I set the value of the next column value? Here, I have the counter "counter" which adds the number of true boolean values in the sampleTable. What I want to do is to set the value of the data in the next column of the table, for the "total". the "total" data should be the counter value. What should I do about this?
private void tableTest(){
int nRow = sampleTable.getRowCount();
int nCol = sampleTable.getColumnCount();
int counter = 0;
Object[][] tableData = new Object[nRow][nCol];
for (int i = 0 ; i < nRow ; i++){
for (int j = 3 ; j < nCol ; j++){
tableData[i][j] = sampleTable.getValueAt(i,j);
System.out.println(tableData[i][j]);
if(tableData[i][j] != null && tableData[i][j].equals(true)){
counter++;
}
}
/* if(nCol == 7){
sampleTable.setValueAt(i, 7, counter);
}else{
tableData = new Object[nRow][nCol + 1];
sampleTable.setValueAt(i, 7, counter);
}*/
System.out.println(counter);
sampleTable.setValueAt(i,7,counter);
counter = 0;
}
}
Without more to go on, it's impossible to know 1. What you're trying to do and 2. What you might be doing wrong...
The following example is really, simple. What it does is allows you to is make changes to the table and then hit the "Update" button which then goes through and calculates the total for each row...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
public class TallyTableTest {
public static void main(String[] args) {
new TallyTableTest();
}
public TallyTableTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
final MyTableModel model = new MyTableModel();
loadData(model);
JTable table = new JTable(model);
JButton update = new JButton("Update");
update.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int row = 0; row < model.getRowCount(); row++) {
int counter = 0;
for (int col = 3; col < 7; col++) {
Object value = model.getValueAt(row, col);
if (value instanceof Boolean && (boolean)value) {
counter++;
}
}
model.setValueAt(counter, row, 7);
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.add(update, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public void loadData(MyTableModel model) throws IOException {
// Fill your model here
}
public static class MyTableModel extends AbstractTableModel {
protected static final String[] COLUMNS = new String[]{
"ID", "First Name", "Last Name", "1", "2", "3", "4", "total"
};
protected static final Class[] COLUMN_TYPES = new Class[]{
Integer.class, String.class, String.class,
Boolean.class, Boolean.class, Boolean.class, Boolean.class,
Integer.class
};
private List<Object[]> rows;
public MyTableModel() {
rows = new ArrayList<>(25);
}
public void addRow(Object[] data) {
rows.add(data);
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return COLUMNS.length;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return COLUMN_TYPES[columnIndex];
}
#Override
public String getColumnName(int column) {
return COLUMNS[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object[] row = rows.get(rowIndex);
return row[columnIndex];
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Object[] row = rows.get(rowIndex);
row[columnIndex] = aValue;
fireTableCellUpdated(rowIndex, columnIndex);
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex >= 3 && columnIndex <= 6;
}
}
}
What the example does it updates the total in real time. What this means, is each time you change a column value for a row, it re-calculates that rows total and updates the model internally.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
public class TallyTableTest {
public static void main(String[] args) {
new TallyTableTest();
}
public TallyTableTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
final MyTableModel model = new MyTableModel();
loadData(model);
JTable table = new JTable(model);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public void loadData(MyTableModel model) throws IOException {
// Fill your model here...
}
public static class MyTableModel extends AbstractTableModel {
protected static final String[] COLUMNS = new String[]{
"ID", "First Name", "Last Name", "1", "2", "3", "4", "total"
};
protected static final Class[] COLUMN_TYPES = new Class[]{
Integer.class, String.class, String.class,
Boolean.class, Boolean.class, Boolean.class, Boolean.class,
Integer.class
};
private List<Object[]> rows;
public MyTableModel() {
rows = new ArrayList<>(25);
}
public void addRow(Object[] data) {
rows.add(data);
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return COLUMNS.length;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return COLUMN_TYPES[columnIndex];
}
#Override
public String getColumnName(int column) {
return COLUMNS[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object[] row = rows.get(rowIndex);
return row[columnIndex];
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Object[] row = rows.get(rowIndex);
row[columnIndex] = aValue;
int counter = 0;
for (int col = 3; col < 7; col++) {
Object value = row[col];
if (value instanceof Boolean && (boolean) value) {
counter++;
}
}
row[7] = counter;
fireTableCellUpdated(rowIndex, columnIndex);
fireTableCellUpdated(rowIndex, 7);
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex >= 3 && columnIndex <= 6;
}
}
}
I have created my JTable like this:
String[] columns = {"Country", "Continent", "Latitude", "Longitude"};
String[][] data = {{"A","B","C","D"}};
table = new JTable(data,columns);
JScrollPane spTable = new JScrollPane(table);
panel2.add(spTable);
Now I want to change the look of the table in such a way that rows will be exchanged with columns, meaning that the table will have 4 rows and 1 column. Could not find such function between member methods, is it possible? Thanks.
To do that, I would consider a custom TableModel which can handle a "toggled" state.
From your example, the result may be surprizing but this code shows you the general idea and allows you to swap rows and columns with a button.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
public class TestTable {
private static class TogglingTableModel extends AbstractTableModel {
private boolean toggled = false;
private final Object[][] data;
private final Object[] columnNames;
public TogglingTableModel(Object[][] data, Object[] columnNames) {
this.columnNames = columnNames;
this.data = data;
normalizeData();
}
private void normalizeData() {
for (int i = 0; i < data.length; i++) {
Object[] o = data[i];
if (o.length < columnNames.length) {
data[i] = Arrays.copyOf(o, columnNames.length);
}
}
}
#Override
public String getColumnName(int column) {
if (toggled) {
Object valueAt;
if (column == 0) {
valueAt = columnNames[0];
} else {
valueAt = data[column - 1][0];
}
return valueAt != null ? valueAt.toString() : null;
} else {
Object object = columnNames[column];
return object != null ? object.toString() : null;
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public int getColumnCount() {
if (toggled) {
return data.length + 1;
} else {
return columnNames.length;
}
}
#Override
public int getRowCount() {
if (toggled) {
return columnNames.length - 1;
} else {
return data.length;
}
}
#Override
public Object getValueAt(int row, int column) {
if (toggled) {
if (column == 0) {
return columnNames[row + 1];
} else {
return data[column - 1][row + 1];
}
} else {
return data[row][column];
}
}
#Override
public void setValueAt(Object aValue, int row, int column) {
if (toggled) {
if (column == 0) {
columnNames[row + 1] = aValue;
} else {
data[column - 1][row + 1] = aValue;
}
} else {
data[row][column] = aValue;
}
}
public boolean isToggled() {
return toggled;
}
public void toggle() {
toggled = !toggled;
fireTableStructureChanged();
}
}
private TogglingTableModel tableModel;
public TestTable() {
JFrame frame = new JFrame(TestTable.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] columns = { "Country", "Continent", "Latitude", "Longitude" };
String[][] data = { { "A" }, { "B" }, { "C" }, { "D" }, { "E" } };
tableModel = new TogglingTableModel(data, columns);
JTable table = new JTable(tableModel);
JPanel buttonPanel = new JPanel();
JButton togglingButton = new JButton("Toggle table");
togglingButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tableModel.toggle();
}
});
buttonPanel.add(togglingButton);
frame.add(new JScrollPane(table));
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TestTable fs = new TestTable();
}
});
}
}
I've a subclass of JTable that uses a custom table model (an implementation of AbstractTableModel) to manage data.
The problem occurs when I try to delete a row with the method deleteRow. The row in my table is replaced by a blank string but the row is not deleted.
Here is the code:
public class LiveSearchTableModel extends AbstractTableModel
{
private List<String> columnNames = new ArrayList<String>();
private Map<Point, Object> displayData = new HashMap<Point, Object>();
private Map<Point, Object> originalData = new HashMap<Point, Object>();
public LiveSearchTableModel(List<String> columnNames,
Map<Point, Object> tableData)
{
this.columnNames = columnNames;
this.displayData = tableData;
this.originalData.putAll(tableData);
}
#Override
public int getColumnCount() {
return columnNames.size();
}
#Override
public int getRowCount() {
return displayData.size() / columnNames.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return displayData.get(new Point(rowIndex, columnIndex));
}
public void deleteRow (int row)
{
for (int cont = 0; cont < columnNames.size();cont++)
{
displayData.remove(new Point (row,cont));
}
this.fireTableRowsDeleted(row, row);
}
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex)
{
this.displayData.put(new Point(rowIndex, columnIndex), value);
this.fireTableDataChanged();
}
}
The sscce below illustrates one potential problem: The keys of a Map are not ordered, while the rows of a table are. In the approach shown, an array of keys must by updated with each change to the data. See also this related example. If required, you could extend Point to implement Comparable, as shown here for Value.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
/**
* #see https://stackoverflow.com/q/12330167/230513
*/
public class TableModelTest extends JPanel {
public TableModelTest() {
super(new BorderLayout());
final MyModel model = new MyModel();
JTable table = new JTable(model);
this.add(new JScrollPane(table));
this.add(new JButton(new AbstractAction("Delete") {
#Override
public void actionPerformed(ActionEvent e) {
model.remove(0);
}
}), BorderLayout.SOUTH);
}
public class MyModel extends AbstractTableModel {
private List<String> names = new ArrayList<String>();
private Map<Point, Object> data = new HashMap<Point, Object>();
private Point[] keys;
public MyModel() {
this.names = Arrays.asList("Point", "Name");
data.put(new Point(1, 1), "One");
data.put(new Point(2, 2), "Two");
data.put(new Point(3, 3), "Three");
this.keys = data.keySet().toArray(new Point[data.size()]);
}
public void remove(int row) {
data.remove(keys[row]);
keys = data.keySet().toArray(new Point[data.size()]);
this.fireTableRowsDeleted(row, row);
}
#Override
public int getColumnCount() {
return names.size();
}
#Override
public String getColumnName(int col) {
return names.get(col);
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public Object getValueAt(int row, int col) {
if (col == 0) {
return keys[row];
} else {
return data.get(keys[row]);
}
}
}
private void display() {
JFrame f = new JFrame("TableModelTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new TableModelTest().display();
}
});
}
}