I have Components I have created that are being put into a table model with two columns as below.
if (!newAcList.isEmpty()) {
for (Acronym acc : newAcList) {
tableModel.addRow(new String[]{acc.getName(), acc.getDefinition()});
}
}
What I need is when the user selects an item on the table model it converts the item back to my Acronym Object. I am using a Listselectionevent Listener.
Here is valueChanged selection event``
#Override
public void valueChanged(ListSelectionEvent e) {
String selectedAcData = null;
String selectDefData = null;
int[] selectedRow = accTable.getSelectedRows();
int[] selectedColumns = accTable.getSelectedColumns();
for (int i = 0; i < selectedRow.length; i++) {
// for (int j = 0; j < selectedColumns.length; j++) {
selectedAcData = (String) accTable.getValueAt(selectedRow[i], 0);
}
}
You might want to create a class that implements the TableModel interface for the acronyms. It might be called AcronymTableModel and is backed by a List<Acronym> list of Acronyms. Then give this model to your table.
The call to accTable.getValueAt(selectedRow[i], 0); in your valueChanged method will then return an instance of an Acronym.
Here's a quick example.
public class Example {
public static void main(String [] a) {
JFrame f = new JFrame();
JPanel p = new JPanel();
List<Acronym> acronyms = new ArrayList<Acronym>();
acronyms.add(new Acronym("FBI", "Federal Bureau of Investigation"));
acronyms.add(new Acronym("CIA", "Central Intelligence Agency"));
final TableModel tModel = new AcronymTableModel(acronyms);
JTable t = new JTable(tModel);
t.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
Acronym a = (Acronym)tModel.getValueAt(e.getFirstIndex(), 0);
System.out.println(a.acronym + ": " + a.definition);
}});
p.add(t);
f.getContentPane().add(p);
f.pack();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
class Acronym {
String acronym;
String definition;
public Acronym(String a, String d) {
acronym = a;
definition = d;
}
}
class AcronymTableModel implements TableModel {
private List<Acronym> acronyms;
public AcronymTableModel(List<Acronym> acs) {
this.acronyms = new ArrayList<Acronym>(acs);
}
#Override
public int getRowCount() {
return this.acronyms.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public String getColumnName(int columnIndex) {
switch(columnIndex) {
case 0:
return "Acronym";
case 1:
return "Definition";
}
return null;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return String.class; // Since both columns are simply
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return acronyms.get(rowIndex);
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
#Override
public void addTableModelListener(TableModelListener l) {
}
#Override
public void removeTableModelListener(TableModelListener l) {
}
}
The Java tutorials are always good and have good examples.
http://docs.oracle.com/javase/tutorial/uiswing/events/listselectionlistener.html
Related
I have a JTable that is used to capture user input which later will be printed upon hitting the Print button. I have an image that I would want to be the header and another one to be a footer.an image showing this can be found here. I have followed the example that I found from oracle documents here. I want it exactly the way it is done in TablePrintdemo3 here.
Allow me to post the classes here.
Here is my first class:
public class Product {
String productDescription;
Double productPrice;
//dummy properties
Integer productQuantity;
Double productTotalAmount;
public Product() {
this.productDescription = "";
this.productPrice = 0.0;
this.productTotalAmount = 0.0;
this.productQuantity = 0;
}//getters and setters here
}
The second class is a custom model as shown here:
public class ProductTableModel extends AbstractTableModel {
private final List<String> columnNames;
private final List<Product> products;
public ProductTableModel() {
String[] header = new String[] {
"Quantity",
"Description",
"Unity Price",
"Total Price"
};
this.columnNames = Arrays.asList(header);
this.products = new ArrayList<>();
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0: return Integer.class;
case 1: return String.class;
case 2: return Double.class;
case 3: return Double.class;
default: throw new ArrayIndexOutOfBoundsException(columnIndex);
}
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Product product = this.getProduct(rowIndex);
switch (columnIndex) {
case 0: return product.getProductQuantity();
case 1: return product.getProductDescription();
case 2: return product.getProductPrice();
case 3: return product.getProductTotalAmount();
default: throw new ArrayIndexOutOfBoundsException(columnIndex);
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex < 0 || columnIndex >= getColumnCount()) {
throw new ArrayIndexOutOfBoundsException(columnIndex);
} else {
Product product = this.getProduct(rowIndex);
switch (columnIndex) {
case 0: product.setProductQuantity((Integer)aValue); break;
case 1: product.setProductDescription((String)aValue); break;
case 2: product.setProductPrice((Double)aValue); break;
case 3: product.setProductTotalAmount((Double)aValue); break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
}
#Override
public int getRowCount() {
return this.products.size();
}
#Override
public int getColumnCount() {
return this.columnNames.size();
}
#Override
public String getColumnName(int columnIndex) {
return this.columnNames.get(columnIndex);
}
public void setColumnNames(List<String> columnNames) {
if (columnNames != null) {
this.columnNames.clear();
this.columnNames.addAll(columnNames);
fireTableStructureChanged();
}
}
public List<String> getColumnNames() {
return Collections.unmodifiableList(this.columnNames);
}
public void addProducts(Product product) {
int rowIndex = this.products.size();
this.products.add(product);
fireTableRowsInserted(rowIndex, rowIndex);
}
public void addProducts(List<Product> productList) {
if (!productList.isEmpty()) {
int firstRow = this.products.size();
this.products.addAll(productList);
int lastRow = this.products.size() - 1;
fireTableRowsInserted(firstRow, lastRow);
}
}
public void addEmptyRow(){
products.add(new Product());
this.fireTableRowsInserted(products.size()-1, products.size()-1);
}
public void insertProduct(Product product, int rowIndex) {
this.products.add(rowIndex, product);
fireTableRowsInserted(rowIndex, rowIndex);
}
public void deleteProduct(int rowIndex) {
if (this.products.remove(this.products.get(rowIndex))) {
fireTableRowsDeleted(rowIndex, rowIndex);
}
}
public Product getProduct(int rowIndex) {
return this.products.get(rowIndex);
}
public List<Product> getProducts() {
return Collections.unmodifiableList(this.products);
}
public void clearTableModelData() {
if (!this.products.isEmpty()) {
int lastRow = products.size() - 1;
this.products.clear();
fireTableRowsDeleted(0, lastRow);
}
}
}
The third class is my is as follows:
public class NiceTablePrinting extends MainClass{
#Override
protected JTable initializeTable(TableModel model) {
return new NicePrintingJTable(model);
}
private static class NicePrintingJTable extends JTable {
public NicePrintingJTable(TableModel model) {
super(model);
}
/**
* Overridden to return a fancier printable, that wraps the default.
* Ignores the given header and footer. Renders its own header.Always
* uses the page number as the footer.
*/
#Override
public Printable getPrintable(PrintMode printMode,
MessageFormat headerFormat,
MessageFormat footerFormat) {
MessageFormat pageNumber = new MessageFormat("- {0} -");
/* Fetch the default printable */
Printable delegate = per.getPrintable(printMode,null,pageNumber);
/* Return a fancy printable that wraps the default */
return new NicePrintable(delegate);
}
}
private static class NicePrintable implements Printable {
Printable delegate;
//
BufferedImage header;
BufferedImage footer;
//
boolean imagesLoaded;
{
try{
header=ImageIO.read(getClass().getResource("images/header.PNG"));
footer=ImageIO.read(getClass().getResource("images/footer.PNG"));
imagesLoaded=true;
}
catch(IOException ex)
{
ex.printStackTrace();
}
imagesLoaded=false;
}
public NicePrintable(Printable delegate) {
this.delegate = delegate;
}
#Override
public int print(Graphicsg,PageFormatpf,intpi)throwsPrinterException
{
if(!imagesLoaded){
return delegate.print(g, pf, pi);
}
//top origin
int x=(int)pf.getImageableX();
int y=(int)pf.getImageableY();
//
int iw=(int)pf.getImageableWidth();
int ih=(int)pf.getImageableHeight();
//image header
int hh= header.getHeight();
int hw=header.getWidth();
//image footer
int fh=footer.getHeight();
int fw=footer.getWidth();
int fY=ih-fh-10;
int fX=x;
//calculating the area to print the table
int tableX=10;
int tableY=hh +10;
int tableW=iw-20;
int tableH=ih-hh-10-fh-10;
/* create a new page format representing the shrunken area to print the table into */
PageFormat format = new PageFormat() {
#Override
public double getImageableX() {return tableX;}
#Override
public double getImageableY() {return tableY;}
#Override
public double getImageableWidth() {return tableW;}
#Override
public double getImageableHeight() {return tableH;}
};
/*
* We'll use a copy of the graphics to print the table to. This protects
* us against changes that the delegate printable could make to the graphics
* object.
*/
Graphics gCopy = g.create();
/* print the table into the shrunken area */
int retVal = delegate.print(gCopy, format, pi);
/* if there's no pages left, return */
if (retVal == NO_SUCH_PAGE) {
return retVal;
}
/* dispose of the graphics copy */
gCopy.dispose();
//draw the images
g.drawImage(header, x, y, hw, hh, null);
g.drawImage(footer, fX, fY, fw, fh, null);
return Printable.PAGE_EXISTS;
}
}
}
The fourth class is as follows:
public class MainClass {
private JTable table;
JFrame frame;
JButton print;
JScrollPane sp;
ProductTableModel model;
public MainClass(){
frame= new JFrame("Test Printing");
frame.setLayout(new java.awt.BorderLayout());
frame.setVisible(true);
///create table
model=new ProductTableModel();
table=this.initializeTable(model);
model.addEmptyRow();
table.setPreferredScrollableViewportSize(newjava.awt.Dimension(300,300));
sp= new javax.swing.JScrollPane(table);
frame.add(sp);
//button
print= new JButton("Print");
frame.add(print,BorderLayout.SOUTH);
frame.pack();
print.addActionListener((ActionEvent e) -> {
try {
printTable();
} catch (PrinterException ex) {
Logger.getLogger(MainClass.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
protected JTable initializeTable(TableModel model) {
return new JTable(model);
}
public void printTable() throws PrinterException {
table.print(JTable.PrintMode.NORMAL, null, null, true, null, true);
}
public static void main(String [] args){
MainClass cl= new MainClass();
}
}
I would want to set my things the way it is done in TablePrintdemo3. Now I cannot see where I have gone wrong. Please assist.
The problem is it is printing only the table -no header and footer images.
Attempting to create a custom JTable structure, I started with a very simple project to better understand. Unfortunately, as soon as I start to customize stuff, I get weird behaviours and I would like you to help me understand them. Thank you very much.
Here is my small project :
public class Tableau extends JFrame {
public Tableau() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800,600);
setContentPane(new Panel());
setVisible(true);
}
public static void main(String[] args) {
new Tableau();
}
private static class Panel extends JPanel {
private JTable table = new Table(4, 4);
public Panel() {
add(table);
}
}
private static class Table extends JTable {
private Renderer randerer = new Renderer();
public Table(int row, int col) {
super(new Model(row, col));
setAutoResizeMode(AUTO_RESIZE_OFF);
setDefaultRenderer(String.class, randerer);
setDefaultEditor(String.class, randerer);
}
private class Renderer implements TableCellRenderer, TableCellEditor {
String previousContent = "";
JTextPane rendererComponent = new JTextPane();
public Renderer() {
super();setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
rendererComponent.setText((String)value);
rendererComponent.setBorder(hasFocus ? BorderFactory.createLineBorder(Color.RED) : null);
rendererComponent.setBackground(isSelected ? Color.PINK : Color.GREEN);
FontMetrics fm = rendererComponent.getFontMetrics(rendererComponent.getFont());
if(((String)value).length()!=0) {rendererComponent.setPreferredSize(new Dimension(fm.stringWidth((String)value),fm.getHeight()));}
else {rendererComponent.setPreferredSize(new Dimension(20, fm.getHeight()));}
return rendererComponent;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
rendererComponent.setText((String)value);
rendererComponent.setBackground(isSelected ? table.getSelectionBackground() : Color.MAGENTA);
if(isSelected) {rendererComponent.selectAll();}
previousContent = (String)value;
return rendererComponent;
}
#Override
public Object getCellEditorValue() {
return rendererComponent.getText();
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
fireEditingStoppedEvent();
return true;
}
#Override
public void cancelCellEditing() {
rendererComponent.setText(previousContent);
fireEditingCanceledEvent();
}
protected void fireEditingStoppedEvent() {
for(CellEditorListener l : listeners) {l.editingStopped(new ChangeEvent(this));}
}
protected void fireEditingCanceledEvent() {
for(CellEditorListener l : listeners) {l.editingCanceled(new ChangeEvent(this));}
}
private List<CellEditorListener> listeners = new LinkedList<CellEditorListener>();
#Override
public void addCellEditorListener(CellEditorListener l) {
listeners.add(l);
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
listeners.remove(l);
}
}
}
private static class Model implements TableModel {
// private ColumnModel colonnes = new ColumnModel();
private List<List<Cellule>> colonnes = new LinkedList<List<Cellule>>();
private int rowCount = 0;
// private List<Cellule> cellules = new LinkedList<Cellule>();
private static class Cellule {
public Cellule() {}
public Cellule(Object content) {this.content = content;}
private Object content;
private Object getContent() {return content;}
private void setContent(Object newContent) {content = newContent;}
}
public Model(int row, int col) {
for(int j=0; j<col; j++) {
insertColumn(j);
}
for(int i=0; i<row; i++) {
insertRow(i);
}
}
#Override
public int getRowCount() {
return rowCount;
}
#Override
public int getColumnCount() {
return colonnes.size();
}
#Override
public String getColumnName(int columnIndex) {
String result = "";
for (; columnIndex >= 0; columnIndex = columnIndex / 26 - 1) {
result = (char)((char)(columnIndex%26)+'A') + result;
}
return result;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return colonnes.isEmpty() ? Object.class : getValueAt(columnIndex, 0).getClass();
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return colonnes.get(columnIndex).get(rowIndex).getContent();
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
colonnes.get(columnIndex).get(rowIndex).setContent(aValue);
fireTableChanged(new TableModelEvent(this, rowIndex, rowIndex, columnIndex, TableModelEvent.UPDATE));
}
protected void fireTableChanged(TableModelEvent e) {
for(TableModelListener l : listeners) {
l.tableChanged(null);
}
}
public void insertColumn(int index) {
List<Cellule> newColumn = new LinkedList<Cellule>();
for(int i = 0; i<getRowCount(); i++) {
Cellule newCell = new Cellule("");
newColumn.add(newCell);
}
colonnes.add(index, newColumn);
fireTableChanged(new TableModelEvent(this, 0, getRowCount(), index, TableModelEvent.INSERT));
}
public void insertRow(int index) {
for(List<Cellule> colonne : colonnes) {
Cellule newCell = new Cellule("");
colonne.add(index, newCell);
}
rowCount++;
fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void removeColumn(int index) {
colonnes.remove(index);
fireTableChanged(new TableModelEvent(this, 0, getRowCount(), index, TableModelEvent.DELETE));
}
public void removeRow(int index) {
for(List<Cellule> row : colonnes) {
row.remove(index);
}
rowCount--;
fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
}
private List<TableModelListener> listeners = new LinkedList<TableModelListener>();
#Override
public void addTableModelListener(TableModelListener l) {
listeners.add(l);
}
#Override
public void removeTableModelListener(TableModelListener l) {
listeners.remove(l);
}
}
}
Basically, we have a JFrame (class Tableau), containing a JPanel (class Panel) containing a JTable (class Table). This Table uses a TableModel (class Model) and a JTextPane (class Renderer) that will serve for both rendering and editing the table content.
Here are my problems :
1) If I click a cell, it becomes white (which I don't understand how it is possible given the code of the renderer...). If I write something, first, nothing appears in the cell, but then, when I move the focus, the text appears...
2) If I click a cell and then move the focus using arrow keys, only then the selections seems to be done correctly. The red border is correctly displayed, etc. Why is the selection incorrect when I just click, without using arrows ?
Thanks !
The purpose of this code is, fill the table with random numbers when something is write in the cell[0,1];
the problem is that the table do not automatically refresh itself.
The table refresh the content only when i move a border or i click on the cells.
import javax.swing.table.TableModel;
public abstract class AbstractTableData implements TableModel{
public static AbstractTableData getTabellaDati(){
throw new UnsupportedOperationException("");
};
#Override
abstract public boolean isCellEditable(int rowIndex, int columnIndex);
}
/---------------------------------------------------/
import java.util.Random;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
public class TableData extends AbstractTableData{
public static final int N_C = 10;
public static final int N_R = 10;
public String[] heading;
public String[][] data;
public TableData(String[] h, String[][] data) {
this.heading = h;
this.data = data;
}
#Override
public int getRowCount() {
return heading.length;
}
#Override
public int getColumnCount() {
return data.length;
}
#Override
public String getColumnName(int columnIndex) {
return heading[columnIndex];
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return "".getClass();
}
#Override
public boolean isCellEditable(int rowIndex, int columnsIndex) {
if (rowIndex == 0) {
if (columnsIndex == 0) {
return false;
} else {
return true;
}
} else {
return false;
}
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
data[rowIndex][columnIndex] = (String)aValue;
fireTableUpadate(rowIndex, columnIndex);
}
#Override
public void addTableModelListener(TableModelListener l) {
}
#Override
public void removeTableModelListener(TableModelListener l) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
private void fireTableUpadate(int rowIndex, int columnIndex)
{
Random ran =new Random();
for(int i=1;i<N_R;i++)
for(int j=0;j<N_R;j++)
data[i][j]=""+ran.nextInt();
}
}
/------------------------------------------/
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
public class Test {
public static void main(String[] args) {
String[] head = new String[TableData.N_C];
String[][] data = new String[TableData.N_R][TableData.N_C];
for (int i = 0; i < TableData.N_C; i++) {
head[i] = "" + i;
}
for (int i = 0; i < TableData.N_R; i++) {
for (int j = 0; j < TableData.N_C; j++) {
data[i][j] = "";
}
}
data[0][0]="->";
JTable table = new JTable(data, head);
table.setModel(new TableData(head,data));
JPanel panel = new JPanel();
JFrame frame = new JFrame();
frame.add(panel.add(table));
frame.setSize(1000, 380);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
AbstractTableData has to remain the same.
I hope someone will find what's wrong!
I am trying to add image Icon in Jtable's cell. I have a code as mentioned below. What should I do for that?
package com.orb;
private final LinkedList<Product> list= new LinkedList<Product>();
private final LinkedList<Boolean> checkList = new LinkedList<Boolean>();
public void addItem(Product customer) {
list.add(customer);
checkList.add(false);
checkList.remove(true);
fireTableDataChanged();
}
#Override
public int getColumnCount() {
return 6;
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object obj = null;
if(columnIndex==4){
setTotal(list.get(rowIndex));
}
switch (columnIndex){
case 0: obj= list.get(rowIndex).getCode() ;break;
case 1: obj=list.get(rowIndex).getDescription(); break;
case 2: obj=list.get(rowIndex).getQuantity();break;
case 3: obj=list.get(rowIndex).getPrice();break;
case 4: obj=list.get(rowIndex).getTotal();break;
}
return obj;
}
#Override
public Class<?> getColumnClass(int arg0) {
switch(arg0){
case 0: case 1: return String.class;
case 2: return Integer.class;
case 3: case 4: return Double.class;
//case 5: return ImageIcon.class;
}
return super.getColumnClass(arg0);
}
#Override
public boolean isCellEditable(int arg0, int arg1) {
boolean isCellEditable = false;
switch(arg1){
case 2: case 3: isCellEditable= true;break;
default: isCellEditable= false;break;
}
return isCellEditable;
//return super.isCellEditable(arg0, arg1);
}
#Override
public void setValueAt(Object arg0, int arg1, int arg2) {
System.out.println("Value seted" +arg0 + arg1 + arg2);
switch(arg2){
case 0: break;
case 1: break;
case 2: list.get(arg1).setQuantity((Integer)arg0); setTotal(list.get(arg1)); break;
case 3: list.get(arg1).setPrice((Double)arg0); setTotal(list.get(arg1));break;
case 4: list.get(arg1).setTotal((Double)arg0);break;
//case 0: checkList.set(arg1, (Boolean)arg0);break;
default:break;
}
fireTableDataChanged();
}
public LinkedList<Product> getList() {
LinkedList<Product> temp = new LinkedList<Product>();
int index=-1;
for(Boolean isSelected:checkList){
index++;
if(isSelected){
temp.add(list.get(index));
}
}
return temp;
}
public void deleteRow(int rowNubmer)
{
list.remove(rowNubmer);
fireTableDataChanged();
}
public void setTotal(Product product){
Double total = 0.0d;
total = product.getQuantity ()* product.getPrice();
product.setTotal(total);
}
#Override
public void fireTableDataChanged() {
super.fireTableDataChanged();
}
I have a table model like above. I want to add image icon in table cell and want to delete cell when that icon is pressed. How can I do with this code?
Please give me full description over this.
You can use a DefaltTableCellRenderer which is backed by a JLabel which you can then use to set the icon.
The best solution would be to extend DefaltTableCellRenderer and override the getTableCellRendererComponent method and apply the icon as is needed on a cell by cell need
You can apply renderers either by defining the default renderer for a given Class type or directly to the column
Check out How to Use JTables and Using Custom Renderers in particular
UPDATED with example
This is A approach, there are many more...
public class TestTable {
public static void main(String[] args) {
new TestTable();
}
public TestTable() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JTable table = new JTable();
table.setGridColor(Color.LIGHT_GRAY);
table.setShowGrid(true);
table.setShowHorizontalLines(true);
table.setShowVerticalLines(true);
table.setModel(new TestTableModel());
table.getColumn("X").setCellRenderer(new DeleteCellRenderer());
table.getColumn("X").setCellEditor(new DeleteCellEditor());
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class TestTableModel extends AbstractTableModel {
private List<RowData> rowData;
public TestTableModel() {
rowData = new ArrayList<RowData>(25);
for (int index = 0; index < 10; index++) {
rowData.add(new RowData(index));
}
}
#Override
public String getColumnName(int column) {
return column == 0 ? "Text" : "X";
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
RowData rd = rowData.get(rowIndex);
return rd.isDeletable();
}
#Override
public int getRowCount() {
return rowData.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
RowData rd = rowData.get(rowIndex);
return columnIndex == 0 ? rd.getText() : rd.isDeletable();
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
RowData rd = rowData.get(rowIndex);
if (columnIndex == 1) {
if (aValue instanceof Boolean && (Boolean)aValue) {
rowData.remove(rd);
fireTableRowsDeleted(rowIndex, rowIndex);
}
}
}
}
public class RowData {
private String text;
private boolean deletable;
public RowData(int row) {
text = "Row " + row;
deletable = Math.round(Math.random() * 1) == 0;
}
public String getText() {
return text;
}
public boolean isDeletable() {
return deletable;
}
}
public class DeleteCellRenderer extends DefaultTableCellRenderer {
public DeleteCellRenderer() {
try {
BufferedImage img = ImageIO.read(getClass().getResource("/Delete.png"));
setIcon(new ImageIcon(img));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setText(null);
if (value instanceof Boolean && (Boolean)value) {
setEnabled(true);
} else {
setEnabled(false);
}
return this;
}
}
public class DeleteCellEditor extends AbstractCellEditor implements TableCellEditor {
private JLabel label;
public DeleteCellEditor() {
label = new JLabel("Delete");
}
#Override
public Object getCellEditorValue() {
return true;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
stopCellEditing();
}
});
return label;
}
#Override
public boolean isCellEditable(EventObject e) {
return true;
}
}
}
Updated
Why not use a JButton/TableCellEditor? Here's why
This is done through the custom cell renderer that can extend JLabel. You can easily set the icon for JLabel.
Renderer is a component that must draw itself as a table cell after JTable calls getTableCellRendererComponent passing the cells state and content. It is common for a renderer then to set properties on its own and return this. The renderer can also return some other object as long as it extends Component.
I have a JTable for which I have made a table model. But on passing the column names to table model, it is not updating the column names. Can someone tell me why?
class MyTableModelTwo extends AbstractTableModel {
private Object[][] data;
private String[] columnNames = {"Name", "ID Number", "CGPA"};
public MyTableModelTwo(Object[][] data) {
this.data = data;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
#Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
#Override
public boolean isCellEditable(int rowIndes, int columnIndex) {
return false;
}
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
data[rowIndex][columnIndex] = value;
fireTableCellUpdated(rowIndex, columnIndex);
}
}
class MyTableTwo extends JPanel implements TableModelListener {
private JTable table;
private Object[][] data;
private JTextField t;
public MyTableTwo() {
data = new Object[3][3];
t = new JTextField();
for (int i = 0; i < noElements; i++) {
data[i][0] = "Kaushik";
data[i][1] = "2008A3";
data[i][2] = "7.79";
}
MyTableModelTwo m = new MyTableModelTwo(data);
table = new JTable(m);
}
#Override
public void tableChanged(TableModelEvent e) {
int row = table.getRowCount();
double sum = 0, d = 0;
for (int i = 0; i < row; i++) {
double c = (Double) table.getValueAt(i, 16);
sum += c;
}
t.setText("" + sum);
t.setHorizontalAlignment(JTextField.RIGHT);
}
}
You need to override getColumnName(int index) in your TableModel.
#Override
public String getColumnName(int index) {
return columnNames[index];
}