This question already has answers here:
Dynamically add images to JTable cells
(2 answers)
Closed 9 years ago.
I am wanting to dynamically add data to a JTable including an image. Here is my code:
Main class
String image = matchedSlots.get(i).getImagePath();
String title = matchedSlots.get(i).getTitle();
String director = matchedSlots.get(i).getDirector();
int rating = matchedSlots.get(i).getRating();
int runTime = matchedSlots.get(i).getRunningTime();
searchResults.getColumnModel().getColumn(i).setCellRenderer(new ImageRender(image));
DefaultTableModel tm = (DefaultTableModel) searchResults.getModel();
tm.addRow(new Object[] {image,title,director,rating,runTime});
ImageRenderer Class
public class ImageRender extends DefaultTableCellRenderer{
ImageIcon icon = null;
public ImageRender(String iconName)
{
icon = new ImageIcon(getClass().getResource(iconName));
}
}
This does not work. Only the path name is displayed to the screen. How can I fix this
The simplest way is to modify the TableModel to return Icon.class type for the image column
DefaultTableModel model = new DefaultTableModel(...) {
public Class getColumnClass(int column) {
Class clazz = String.class;
switch (column) {
case IMAGE_COLUMN:
clazz = Icon.class;
break;
}
return clazz;
}
};
Related
I have a JFrame which has a JTable and it can represent data from database. Everything is fine but I want to load or refresh it from another class after a delete operation.
I have already done the delete operation but I can not load the JTable from another class. My code is below:
scrollPane = new JScrollPane();
add(scrollPane, BorderLayout.CENTER);
DefaultTableModel model=null;
try {
model = makeTableModel();
} catch (SQLException | IOException e) {
e.printStackTrace();
}
table = new JTable(model);
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
int row = table.getSelectedRow();
String getvalue = (table.getModel().getValueAt(row, 4).toString());
PopulatePhotographerClass pp=new PopulatePhotographerClass(getvalue);
}
});
table.setRowHeight(200);
scrollPane.setViewportView(table);
Here is my makeTableModel method:
public static DefaultTableModel makeTableModel() throws SQLException, IOException {
DefaultTableModel model = new DefaultTableModel(new String[]{"Image", "Name","Address","mobile-Number","NID"}, 0) {
#Override
public Class<?> getColumnClass(int columnIndex) {
return columnIndex == 0 ? Icon.class : super.getColumnClass(columnIndex);
}
};
String cmd = "select * from photographer_lookup";
try (Connection con =database.DbConnect.getconnection()) {
try (PreparedStatement stmt = con.prepareStatement(cmd)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
String name = rs.getString(3);
Blob blob = rs.getBlob(1);
String address=rs.getString("address");
String mobile=rs.getString("mobile_number");
String nid=rs.getString("Nid");
ImageIcon icon = null;
try (InputStream is = blob.getBinaryStream()) {
BufferedImage img = ImageIO.read(is);
icon = new ImageIcon(img);
}
model.addRow(new Object[]{icon,name,address,mobile,nid});
}
}}}
return model;
}
This is my code that I wrote. Now I want to define a method that does all work which is mentioned above and also it will be called by another class.
First off, you are making a mistake in using view indices to index the model. Listeners and all methods from JTable that return row or column indices will report view indices (except convertXXXIndexToModel methods).
As the table is sorted or columns are moved around, view indices will differ from model indices. JTable will not sort the model or rearrange columns in the model, rather it will change its mapping to the model.
If what you have is view indices and you want to look up cell values, either
Use JTable.getValueAt, which takes view indices
First convert view indices to model indices using JTable.convertRowIndexToModel and JTable.convertColumnIndexToModel before indexing in the model (JTable.getModel()).
Your mouse listener should read:
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
int row = table.getSelectedRow();
if( row < 0 ) return; // check if a row is selected first!
String getvalue = table.getValueAt(row, table.convertColumnIndexToView( 4 ) ).toString(); // use table.getValueAt, this getter takes view indices! Use convertColumnIndexToView to get a view index from a model index!
PopulatePhotographerClass pp=new PopulatePhotographerClass(getvalue);
}
});
Better still would be to implement a ListSelectionListener to listen for selection events, rather than using a MouseListener to act on selection events (thanks #mKorbel for pointing that out). This way you would be notified directly on list selection changes.
If you want operations to be done from another class, write a public method in your class that extends JFrame that does this work. If you have an instance to this class in another class, simply call this newly created public method.
Suppose your JFrame class is called MyFrameWithJTable
public class MyFrameWithJTable extends JFrame {
public void doSomeWork( /*parameters required in the operation*/ ) {
// Does the work you want to call from another class
// Eg the updates you want done in the JTable's model
}
}
Then in another class, if you have an instance of the MyFrameWithJTable class you can do
public class AnotherClass {
private MyFrameWithJTable instance;
public AnotherClass( MyFrameWithJTable instance ) {
this.instance = instance;
}
public void someMethod( ) {
instance.doSomeWork( /*supply parameters*/ );
}
}
Im developing a app for ordeing system and i have to set data into JTabels.
And this code is successfully working.I wanted to know what the importance of and whats happen in this class?
Why we need to import AbstractTabelModel.class?
OrderTabelModel Class:-
public class OrderTableModel extends AbstractTableModel{
protected static final String[] COLUMN_NAMES={"Item","Qty","Amount"};
private List<Order> rows;
public OrderTableModel(List<Order> rows){
this.rows = new ArrayList<>(rows);
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
#Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object value = null;
Order row = rows.get(rowIndex);
switch (columnIndex) {
case 0:
value = row.getItem();
break;
case 1:
value = row.getQty();
break;
case 2:
value = row.getAmount();
break;
}
return value;
}
}
this is other class
private void tblOrderListMouseClicked(java.awt.event.MouseEvent evt) {
int raw = tblOrderList.getSelectedRow();
Order or;
String item;
Double qty,amount,total;
ArrayList<Order> arrOrder = new ArrayList<Order>();
String selectedRaw = tblOrderList.getModel().getValueAt(raw, 0).toString();
System.out.println("order id : "+selectedRaw);
String sql = "select item,qty,amount from orderdetails where orderid='"+selectedRaw+"'";
con = new DBconnector().connect();
try {
Statement ps =con.createStatement();
ResultSet rs2 = ps.executeQuery(sql);
while(rs2.next()){
or = new Order();
or.setItem(rs2.getString("item"));
System.out.println("Item :" +rs2.getString("item"));
or.setQty(rs2.getDouble("qty"));
or.setAmount(rs2.getDouble("amount"));
arrOrder.add(or);
}
rs2.close();
ps.close();
OrderTableModel tblModel = new OrderTableModel(arrOrder);
tblOrderItems.setModel(tblModel);
} catch (Exception e) {
e.printStackTrace();
}
}
Can some one explain me the process of this please?
It is not always mandatory to extend the AbstractTableModel. You can simply extend the DefaultTableModel and only override the getValueAt() method if you have to.
But most of the time for simple usages it is not even needed to override the getValueAt() method either.
By using the DefaultTableModel, you have a limitation for the converting you data (imported from DB) to an object[][] or Vector types which may be a little boring.
But you asked what is the importance of using AbstractTabelModel?
In this case I can say when JTable is started to being rendered, it needs to determine the number of rows and number of the columns and also it needs to know which data should be renedered in each cell and so on. Based on this, JTable ask for this Information from the underlying TableModel. So it is needed for your TableModel(any child or implementation of TableModel) to have those methods which are used by JTable to retrieve the needed information.
Hope this would be helpful.
Good Luck.
Can someone help me with this?
It was working until I changed something trying to optimaze it... damn!
This is my table model:
class MyTableModel extends DefaultTableModel {
private String[] columnNames = {"Last Name","First Name","Next Visit"}; //column header labels
Object[][] data = new Object[100][3];
public void reloadJTable(List<Customer> list) {
for(int i=0; i< list.size(); i++){
data[i][0] = list.get(i).getLastName();
data[i][1] = list.get(i).getFirstName();
if (list.get(i).getNextVisit()==null) {
data[i][2] = "NOT SET";
} else {
String date = displayDateFormat.format(list.get(i).getNextVisit().getTime());
data[i][2] = date;
}
model.addRow(data);
}
}
public void clearJTable() {
model.setRowCount(0);
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
/*
* JTable uses this method to determine the default renderer/
* editor for each cell. If we didn't implement this method,
* then the last column would contain text ("true"/"false"),
* rather than a check box.
*/
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's
* editable.
*/
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
if (col < 2) {
return false;
} else {
return true;
}
}
}
and this is how I implement the JTable:
// these declarations are all private shared across the model
JTable customerTbl;
MyTableModel model;
List<Customer> customers = new ArrayList<Customer>();
SimpleDateFormat displayDateFormat = new SimpleDateFormat ("EEE dd-MM-yyyy 'at' hh:mm");
//JTable configuration
model = new MyTableModel();
customerTbl = new JTable(model);
model.reloadJTable(customers);
customerTbl.setAutoCreateRowSorter(true); //enable row sorters
DefaultRowSorter sorter = ((DefaultRowSorter)customerTbl.getRowSorter()); //default sort by Last Name
ArrayList list = new ArrayList();
list.add( new RowSorter.SortKey(0, SortOrder.ASCENDING));
sorter.setSortKeys(list); //EXCEPTION HERE
sorter.sort();
customerTbl.getColumnModel().getColumn(0).setPreferredWidth(100); //set Last Name column preferred width
customerTbl.getColumnModel().getColumn(1).setPreferredWidth(80); //set First Name column preferred width
customerTbl.getColumnModel().getColumn(2).setPreferredWidth(150); //set Last Visit column preferred width
I'm getting the following exception triggered on:
sorter.setSortKeys(list);
Exception in thread "main" java.lang.IllegalArgumentException: Invalid SortKey
at javax.swing.DefaultRowSorter.setSortKeys(Unknown Source)
at com.vetapp.customer.CustomersGUI.<init>(CustomersGUI.java:128)
at com.vetapp.main.VetApp.main(VetApp.java:31)
I believe it has to do with the TableColumnModel which is not created correctly...
The main problem is that the column count is returning 0 from the TableModel's super class DefaultTableModel. You need to override this method
#Override
public int getColumnCount() {
return columnNames.length;
}
Another side but potentially fatal issue is the fact that getColumnClass is returning the class of elements within the TableModel. This will throw a NullPointerException if the table is empty. Use a class literal instead such as String.class.
Maintaining a separate backing data array is unnecessary for DefaultTableModel. It has already has its own data vector. This approach is used when extending AbstractTableModel.
This question already has answers here:
How to make a JTable non-editable
(7 answers)
Closed 1 year ago.
When a JTable component is created, cell editing is enabled by default. How can I prevent the user from editing the content of a JTable?
You can create a JTable using following code:
JTable jTable = new JTable() {
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int row, int column) {
return false;
};
};
Basically what we are doing here is overriding isCellEditable and always returning false from it. This will make a non editabe JTabel.
A JTable uses an AbstractTableModel object. This is the thing you pass into the constructor of the JTable. You can write your own AbstractTableModel as follows
public class MyTableModel extends AbstractTableModel {
public boolean isCellEditable(int row, int column){
return false;
}
}
and then initialize your JTable as
JTable myTable = new JTable(new MyTableModel());
myTable.setDefaultEditor(Object.class, null);
Have you tryed simply:
JTable table = new JTable();
table.setEnabled(false);
About JComponent.setEnabled(boolean) it sayes:
Sets whether or not this component is enabled. A component that is enabled may respond to user input, while a component that is not enabled cannot respond to user input. Some components may alter their visual representation when they are disabled in order to provide feedback to the user that they cannot take input.
When it comes to JTable it doesnt seem to give any visual feedback at all. With the perk of still being able to click on the column headers. And in my implementation the application could still change the contents of the cells.
Hi I'm working a lot on java so I'm gonna give you my way:
There are two possibilities the first under netbeans. Go to customize code and make it like this:
JTArticleJPAddArrticle = new javax.swing.JTable();
JTArticleJPAddArrticle.setBackground(new java.awt.Color(204, 204, 255));
JTArticleJPAddArrticle.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Reference","Libellé","Marque","Prix d'achat","Prix de vente","Quantité","Total","Etat"
}
){
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
});
jScrollPane8.setViewportView(JTArticleJPAddArrticle);
My other way is to do it is to make an instance of the table model. This is the second way:
model=new DefaultTableModel(head, 0){
#Override
public boolean isCellEditable(int i, int i1) {
return false; //To change body of generated methods, choose Tools | Templates.
}
};
jtable.setmodel(model);
Enjoy this is working well for me. All I want to do is help you guys out because I was helped out a lot earlier.
Well on netbeans you can right click on the table and click on table contents, then you go to the column tab and uncheck the "Editable" checkbox. Greetings!!
I know I am late but hope someone get use of this. You can simple add mouse listener like this:
jtable.addMouseListener( new MouseAdapter () {
#Override
public void mouseClicked ( MouseEvent e ) {
columnIndex = replacedAssets.getSelectedColumn ();
System.out.println ( "Double click on jtable" );
if ( columnIndex == 1 || columnIndex == 2 ) {
JOptionPane.showMessageDialog ( parent , "Editing this Field may cause error in the data." , "Error Edit Not Permitted For This Field" , JOptionPane.ERROR_MESSAGE );
}
}
});
this code prevent editing the columns of indexes 1 and 2 you can remove the if condition to make this work for all columns.
tm = new javax.swing.table.DefaultTableModel()
{
public Class<?> getColumnClass(int column)
{
switch(column)
{
case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
case 3:
return String.class;
case 4:
return String.class;
case 5:
return String.class;
case 6:
return String.class;
case 7:
return String.class;
case 8:
return String.class;
case 9:
return String.class;
case 10:
return String.class;
case 11:
return Boolean.class;
default:
return String.class;
}
}
#Override
public boolean isCellEditable(int row, int column) {
/* Set the 11th column as editable and rest non-
editable */
if(column==11){
return true;
}else{
//all other columns to false
return false;
}
}
};
table = new javax.swing.JTable(tm);
In this method "isCellEditable" we can enable and disable user edit for particular column. In this case enable column=11 and disable rest of the column
I followed Oracle's model for implementing an AbstractTableModel
http://download.oracle.com/javase/tutorial/uiswing/examples/components/TableDemoProject/src/components/TableDemo.java
I did this because my table has to contain 3 columns, and the first has to be a JCheckBox.
Here's my code:
public class FestplattenreinigerGraphicalUserInterfaceHomePagePanelTableModel extends AbstractTableModel {
private String[] columnNames = {"Auswahl",
"Dateiname",
"Pfad"};
private Object[][] data = {
{new Boolean(true), "datei.tmp",
"/home/user/tmp"}
};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col) {
if (col == 0) {
return true;
} else {
return false;
}
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
Here are my questions:
How does JTable (new JTable(FestplattenreinigerGraphicalUserInterfaceHomePagePanelTableModel)) know what the column names are and their values are? Since there's no contructor in my AbstractTableModel?! Is it becaue columnNames and data must be named like they are and JTable accesses them?
How can i put new Values in my JTable? Since columnNames and data are arrays. Can i replace them with vectors? If so, how do I init these vectors? In a constructor in myAbsTableModel?
I think it's very easy to get a solution but this Table handling isn't trivial to me, so thank u very much!
All Swing components come with default model implementations. I suggest you understand how to use them first before trying to create your own. For a JTable its called the DefaultTableModel. Read the API for methods to dynamically add/remove rows of data from the model. Here is a simple example to get you started:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableBasic extends JPanel
{
public TableBasic()
{
String[] columnNames = {"Date", "String", "Integer", "Boolean"};
Object[][] data =
{
{new Date(), "A", new Double(1), Boolean.TRUE },
{new Date(), "B", new Double(2), Boolean.FALSE},
{new Date(), "C", new Double(9), Boolean.TRUE },
{new Date(), "D", new Double(4), Boolean.FALSE}
};
JTable table = new JTable(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers and editors to be used based on Class
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
return o.getClass();
}
return Object.class;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("TableBasic");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TableBasic() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
First, I think you need to learn a bit more about Java, especially inheritance (I'm referencing your constructor problem.
Answers to your questions :
define your column names via a private final static attribute, assuming your column names don't change.
since your class extends AbstractTableModel, you can define a constructor for it, where you'll pass the data. Redefine the getValueAt method to allow the model to use the data you're passing.
Some more advice :
don't do what you're doing in getColumnClass. Normally, all elements in a column will have the same class, so do a switch on the column index to get the classes.
to add a JCheckBox in one of your columns, you'll have to use a custom TableCellRenderer
The JTable determines how many columns by calling getColumnCount() on your column model. It then iterates and calls getColumnName(idx) for each column. Your class tells it the column name -- look at your implementation of those methods.
You can store your data in whatever format you want. The JTable calls methods on your table model to retrieve that data. If you want to add new items to your model, you can implement an addItem(Object o) method to your model; just be sure to call fireTableRowsInserted() for each new item.