sorry but I still don't get this thing from my database dont change to check box. it just show as true or false
try {
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT * FROM tblpdareenlist");
DefaultTableModel model = (DefaultTableModel) viewRecordTable.getModel();
int x = 0;
String b, c, d, e, f, g, h, i;
Boolean a;
while (rs.next()) {
a = rs.getBoolean("colAttend");
b = rs.getString("colNr");
c = rs.getString("colRank");
d = rs.getString("colFName");
e = rs.getString("colMName");
f = rs.getString("colLName");
g = rs.getString("colSN");
h = rs.getString("colUnit");
i = rs.getString("colETE");
model.insertRow(x, new Object[]{a,b,c,d,e,f,g,h,i});
x++;
}
} catch (Exception e) {
JOptionPane.showMessageDialog(rootPane, "Syntax Error\n" + e);
}
The JTable will display a check box for a column if the table model's getColumnClass method returns Boolean.class for that column[1]. You are using the DefaultTableModel which only returns Object.class for any column. This model is just a very simple model, not the best for a real system, more for testing or very simple data.
The best is to implement your own TableModel returning the correct class for given column, e.g. extending the AbstractTableModel.
For testing only you can just extend the DefaultTableModel and override the getColumnClass method:
var model = new DefaultTableModel(0, 3) {
#Override
public Class<?> getColumnClass(int col) {
if (col == 0) return Boolean.class;
else return super.getColumnClass(col);
}
};
var table = new JTable(model);
model.insertRow(0, List.of(false, "false", 0).toArray());
model.insertRow(1, List.of(true, "true", 1).toArray());
JOptionPane.showMessageDialog(null, table);
Again, on the long run, for a real project, you will get stuck very soon with that solution - much better to implement a dedicated TableModel. A very simple (incomplete) example:
public static void main(String[] args) {
var model = new MyTableModel();
var table = new JTable(model);
model.add(new MyData(false, "false", 0));
model.add(new MyData(true, "true", 1));
JOptionPane.showMessageDialog(null, table);
}
static final int FLAG = 0;
static final int NAME = 1;
static final int VALUE = 2;
private static class MyTableModel extends AbstractTableModel {
private final List<MyData> list = new ArrayList<>();
void add(MyData data) {
list.add(data);
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public Object getValueAt(int row, int col) {
var data = list.get(row);
switch(col) {
case FLAG: return data.flag;
case NAME: return data.name;
case VALUE: return data.value;
}
throw new IllegalArgumentException("column " + col);
}
#Override
public Class<?> getColumnClass(int col) {
switch(col) {
case FLAG: return Boolean.class;
case NAME: return String.class;
case VALUE: return Integer.class;
}
throw new IllegalArgumentException("column " + col);
}
}
private static class MyData {
final boolean flag;
final String name;
final int value;
MyData(boolean flag, String name, int value) {
this.flag = flag;
this.name = name;
this.value = value;
}
}
[1] JTable Tutorial
Related
I have JTable that has a column editable. It should get Integer values and update table. But when I edit a cell and go to another cell, the data will erase and goes back to null but the program does not throw any exceptions. How can I fix it?
public class FoodListPanel extends JPanel{
JTable jTable;
FoodTableModel fm;
public FoodListPanel() {
try {
fm = new FoodTableModel(FoodDAO.getAllFoodsFromDB(), new ArrayList<Integer>());
jTable = new JTable(fm) {
public boolean isCellEditable(int data, int columns) {
if(columns<5){
return false;
}
else if(columns ==5){
return true;
}
else if(columns ==6){
if(getValueAt(data, 5)==Boolean.FALSE){
return false;
}
else {
return true;
}
}
else{
return true;
}
}
public Component prepareRenderer(TableCellRenderer r, int data, int columns) {
Component c = super.prepareRenderer(r, data, columns);
return c;
}
};
jTable.setPreferredScrollableViewportSize(new Dimension(650, 420));
jTable.setFillsViewportHeight(true);
JScrollPane jScrollPane = new JScrollPane(jTable);
add(jScrollPane);
} catch (SQLException e) {
e.printStackTrace();
}
}
class FoodTableModel extends AbstractTableModel {
protected String[] cols = {"نامغذا", "دستهبندی", "قیمت", "توضیحات", "عکس" , "تعداد"};
protected Class[] colClasses = {String.class, Integer.class, String.class, String.class,
JLabel.class, Integer.class};
ArrayList<Food> al;
ArrayList<Integer> vals;
public FoodTableModel(ArrayList<Food> foods, ArrayList<Integer> val) {
al = new ArrayList<Food>();
al.addAll(foods);
vals = new ArrayList<Integer>(al.size());
vals.addAll(val);
}
////// TODO: 8/20/16 make dynamic from DB
public int getColumnCount (){return cols.length;}
public int getRowCount (){return al.size();}
public String getColumnName(int col) { return cols[col]; }
public Class getColumnClass(int col) { return colClasses[col]; }
public Object getValueAt(int row, int col){
switch (col) {
case 0:
return al.get(row).getName();
case 1:
return al.get(row).getType();
case 2:
return al.get(row).getPrice();
case 3:
return al.get(row).getDiscreption();
case 5:
if(vals.size()>= al.size()) return vals.get(row);
default:
return null;
}
}
////https://stackoverflow.com/questions/39066012/index-out-of-bound-exception-when-setting-value-to-jtable
public void setValueAt(Object vlaue, int row, int column){
if (column==6){
this.vals.set(row, (Integer)vlaue);
}
this.fireTableCellUpdated(row, column);
this.fireTableDataChanged();
}
/*public void setCols(String[] columns){
cols = columns;
}
public void setClasses(Class[] classes){
colClasses = classes;
}*/
}
}
the data will erase and goes back to null
Your getValuaAt(..) and setValueAt() methods are out of sync.
In the setValueAt() you only save the data for column 6.
In the getValueAt() you only return the data for columns 0-5 and return null for column 6.
You need to fix the getValueAt(...) method to return the actual data, not null.
Also, the setValueAt(...) method should only invoke the fireTableCellUpdated(...) method not the fireTableDataChanged(...) method.
I add items to a model that is linked to a table. When I select an item in this table, things happen depending on what item it is. For now I just have a System.out telling me the items name.
If I have two items called 'A' and 'B', when I select either their respective name is written to the console as expected, however, if I sort them by name, so that 'B' is placed in the row over 'A', the sorting never happened internally but only visually. So if I now select 'A', the console prints out 'B', and vice versa.
The sorter is declared in the mainclass, itemList is a JTable itemList.setAutoCreateRowSorter(true);
Apparently I must have failed to include some default method that's needed for this sorterfunctionality. "default methods" is declared towards the end in the code-snippet, from and after the method 'getColumnName'.
class ItemModel extends AbstractTableModel
{
ArrayList<MCItem> items = new ArrayList<MCItem>();
private int currentMaxRows = 0;
private String[] columnNames = {"Item", "Total Units", "In Sorter"};
private Class[] types = {String.class, Integer.class, Integer.class};
private Object[][] data = new Object[currentMaxRows][getColumnCount()];
public ArrayList<MCItem> getItems()
{
return items;
}
public void readdItems(Main m, ArrayList<MCItem> tempItems)
{
for(MCItem mci : tempItems)
{
mci.setMain(m);
addRow(mci);
}
}
public void emptyMe()
{
currentMaxRows = 0;
items.clear();
data = new Object[currentMaxRows][getColumnCount()];
fireTableDataChanged();
}
public boolean isDuplicate(String s)
{
for(MCItem ci : items)
if(ci.getName().equalsIgnoreCase(s))
return true;
return false;
}
public void updateItem(String id)
{
try
{
int foundRow = -1;
for(int i = 0;i < currentMaxRows;i++)
if(getValueAt(i, 0).toString().equalsIgnoreCase(id))
{
foundRow = i;
break;
}
for(MCItem ii : items)
if(ii.getName().equalsIgnoreCase(id))
{
setItem(foundRow, ii);
fireTableDataChanged();
return;
}
}
catch(NullPointerException e){}
}
public void addRow(MCItem item)
{
//check if we need to expand the dataArray
if(currentMaxRows == items.size())
{
if(currentMaxRows == 0)
data = new Object[++currentMaxRows][getColumnCount()];
else
{
Object[][] tempArr = data;
data = new Object[++currentMaxRows][getColumnCount()];
for(int x = 0; x < tempArr.length; x++)
for(int y = 0; y < getColumnCount(); y++)
data[x][y] = tempArr[x][y];
}
}
setItem(items.size(), item);
items.add(item);
fireTableDataChanged();
}
public void changeItem(int row, String name)
{
String originalName = (String) data[row][0];
data[row][0] = name;
for(MCItem ii : items)
if(ii.getName().toString().equalsIgnoreCase(originalName))
{
ii.setName(name);
return;
}
fireTableDataChanged();
}
public void removeItem(String id)
{
for(MCItem ii : items)
if(ii.getName().toString().equalsIgnoreCase(id))
{
items.remove(ii);
redoList();
return;
}
fireTableDataChanged();
}
private void redoList()
{
ArrayList<MCItem> tempArr = (ArrayList<MCItem>) items.clone();
emptyMe();
for(MCItem ii : tempArr)
addRow(ii);
}
private void setItem(int row, MCItem item)
{
int counter = 0;
data[row][counter++] = item.getName();
data[row][counter++] = item.getCount();
data[row][counter++] = item.getSorterCount();
fireTableDataChanged();
}
MCItem getMCItem(String name)
{
for(MCItem i : items)
if(i.getName().equals(name))
return i;
return null;
}
public String getColumnName(int col)
{
return columnNames[col].toString();
}
public int getRowCount()
{
return data.length;
}
public int getColumnCount()
{
return columnNames.length;
}
public Object getValueAt(int row, int col)
{
return data[row][col];
}
public Class getColumnClass(int columnIndex)
{
return this.types[columnIndex];
}
public boolean isCellEditable(int row, int col)
{
return false;
}
public void setValueAt(Object value, int row, int col)
{
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
* Answer *
The issue was never the tablemodel, but the JTable itself. When I want to present information based on the item selected, I called
currentMCItem = model.getMCItem(model.getValueAt(itemList.getSelectedRow(), 0).toString());
which returned the index in the JTable correctly, however when sorting all the indexes gets messed up and it's only the view that changes, so I had to redo that line to
currentMCItem = model.getMCItem(model.getValueAt(itemList.convertRowIndexToModel(itemList.getSelectedRow()), 0).toString());
So, the key is to call JTable.convertRowIndexToModel(SELECTED INDEX IN TABLE) in order to get the correct index, and use that as if it was the selectedRow.
You have a set of convert methods in JTable that you need to use. For example, convertColumnIndexToModel takes a view index and gives you back a corresponding column index in the model. Convert them and then get the values.
I have been thinking a lot to solve this mistake. But unfortunately I came to final cnclusion that I need help of professionals.
Please, copy,paste this code to see issue:
public class DateFormatDemo extends JFrame
{
private JTable dataSearchResultTable;
public DateFormatDemo()
{
JButton updateTable = new JButton("Update table");
updateTable.setMaximumSize(updateTable.getPreferredSize());
updateTable.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
updateMyTableModel();
}
});
JPanel panel = new JPanel(new GridLayout(2, 1, 5, 10));
panel.setPreferredSize(new Dimension(500, 300));
panel.add(new JScrollPane(initDataSearchResultTable()));
panel.add(updateTable);
super.getContentPane().add(panel);
super.pack();
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
super.setVisible(true);
}
private JTable initDataSearchResultTable()
{
dataSearchResultTable = new JTable();
// dataSearchResultTable.setAutoCreateColumnsFromModel(false);
dataSearchResultTable.setSelectionBackground(new Color(0xaaaaff));
dataSearchResultTable.setFillsViewportHeight(true);
dataSearchResultTable.setRowSelectionAllowed(true);
dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
return dataSearchResultTable;
}
void updateMyTableModel()
{
TableModel tableModel = dataSearchResultTable.getModel();
TableColumnModel columnModel = dataSearchResultTable.getColumnModel();
if (tableModel instanceof MyTableModel) {
((MyTableModel) tableModel).updateModel();
this.initColumnWidths(tableModel, columnModel);
} else {
tableModel = new MyTableModel();
dataSearchResultTable.setModel(tableModel);
this.makeColumnsNotResizable(columnModel);
this.initColumnWidths(tableModel, columnModel);
}
}
private void makeColumnsNotResizable(TableColumnModel columnModel)
{
for (int i = 0; i < columnModel.getColumnCount(); i++) {
if (i == 0 || i == 1) {
columnModel.getColumn(i).setResizable(false);
}
}
}
private void initColumnWidths(TableModel tableModel, TableColumnModel columnModel)
{
TableColumn column = null;
Component comp = null;
int cellWidth = 0;
int headerWidth = 0;
TableCellRenderer headerRenderer = dataSearchResultTable.getTableHeader().getDefaultRenderer();
for (int i = 0; i < columnModel.getColumnCount(); i++) {
column = columnModel.getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, -1, 0);
headerWidth = comp.getPreferredSize().width;
Class<?> columnClass = tableModel.getColumnClass(i);
for (int j = 0; j < tableModel.getRowCount(); j++) {
comp = dataSearchResultTable.getDefaultRenderer(columnClass).getTableCellRendererComponent(
dataSearchResultTable, tableModel.getValueAt(j, i), false, false, j, i);
int width = comp.getPreferredSize().width;
// we cache width of first row. And compare widths of next
// rows with width of first.
// If some row has greater width it becomes width of whole
// row(unless header has greater width)
if (cellWidth < width || j == 0) {
cellWidth = width;
}
}
System.out
.println("columnClass=" + columnClass + ",headerWidth=" + headerWidth + ",cellWidth=" + cellWidth);
if (headerWidth > cellWidth) {
TableCellRenderer centeredRenderer = dataSearchResultTable.getDefaultRenderer(columnClass);
if (centeredRenderer instanceof DefaultTableCellRenderer) {
((DefaultTableCellRenderer) centeredRenderer).setHorizontalAlignment(SwingConstants.CENTER);
column.setCellRenderer(centeredRenderer);
column.setPreferredWidth(headerWidth);
}
} else {
column.setPreferredWidth(cellWidth + 5);
}
}
}
class MyTableModel extends AbstractTableModel
{
private String[] columnNames = { "First Name", "Last Name", "Timestamp", "Number", "Vegetarian" };
private Object[][] data = new Object[5][];
void updateModel()
{
data = new Object[][] {
{ "Vova", "KipokKipokKipokKipok", "2013-04-12 11:20:41", new Integer(5), new Boolean(true) },
{ "Olia", "Duo", "2010-01-11 11:11:41", new Integer(3), new Boolean(false) },
{ "Oksana", "Stack", "2012-04-12 11:20:41", new Integer(2), new Boolean(false) },
{ "Petro", "White", "2010-04-12 11:20:21", new Integer(20), new Boolean(true) },
{ "Ivan", "Brown", "2011-04-11 11:20:41", new Integer(10), new Boolean(true) } };
fireTableDataChanged();
}
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)
{
if (data.length > 0 && data[0] != null) {
return data[row][col];
}
return null;
}
/*
* 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)
{
Object valueAt = getValueAt(0, c);
return valueAt == null ? Object.class : valueAt.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;
}
}
/*
* Don't need to implement this method unless your table's data can
* change.
*/
public void setValueAt(Object value, int row, int col)
{
if (data.length > 0 && data[0] != null) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
}
public static void main(String[] args) throws ParseException
{
new DateFormatDemo();
}
}
Now please click twice on that big button called 'Update Table'. As you see column that should display checkbox as it holds boolean values do not do that but instead displays String true or false.
This code emulates my real workflow.
So, how to update tablemodel to have boolean columns with checkbozes.
Thanks!
take this as simple start point
import java.awt.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
public class Forum implements ListSelectionListener {
private JFrame frame = new JFrame("Frame");
private JPanel fatherCenter = new JPanel();
private JScrollPane tableScroll = new JScrollPane();
private MyTableModel tableModel;
private JTable dialogTable;
private ListSelectionModel lsDialog;
private Color clr;
private Color clr1;
private void addData() {
Runnable doRun1 = new Runnable() {
#Override
public void run() {
tableModel.resetTable();
Vector<String> tbl = new Vector<String>();
Vector<Object> tbl1 = new Vector<Object>();
Random rnd = new Random();
tbl.add("Integer");
tbl.add("Double");
tbl.add("Boolean");
tbl.add("Boolean");
tbl.add("String");
tableModel.setColumnNames(tbl);
for (int row = 0; row < 30; row++) {
tbl1 = null;
tbl1 = new Vector<Object>();
tbl1.addElement(row + 1);
tbl1.addElement(rnd.nextInt(25) + 3.14);
tbl1.addElement((row % 3 == 0) ? false : true);
tbl1.addElement((row % 5 == 0) ? false : true);
if (row % 7 == 0) {
tbl1.add(("Canc"));
} else if (row % 6 == 0) {
tbl1.add(("Del"));
} else {
tbl1.add(("New"));
}
tableModel.addRow(tbl1);
}
addTableListener();
}
};
SwingUtilities.invokeLater(doRun1);
}
private void addTableListener() {
tableModel.addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent tme) {
if (tme.getType() == TableModelEvent.UPDATE) {
System.out.println("");
System.out.println("Cell " + tme.getFirstRow() + ", "
+ tme.getColumn() + " changed. The new value: "
+ tableModel.getValueAt(tme.getFirstRow(),
tme.getColumn()));
}
}
});
}
#Override
public void valueChanged(ListSelectionEvent le) {
int row = dialogTable.getSelectedRow();
int col = dialogTable.getSelectedColumn();
String str = "Selected Row(s): ";
int[] rows = dialogTable.getSelectedRows();
for (int i = 0; i < rows.length; i++) {
str += rows[i] + " ";
}
str += "Selected Column(s): ";
int[] cols = dialogTable.getSelectedColumns();
for (int i = 0; i < cols.length; i++) {
str += cols[i] + " ";
}
str += "Selected Cell: " + dialogTable.getSelectedRow() + ", " + dialogTable.getSelectedColumn();
System.out.println(str);
Object value = dialogTable.getValueAt(row, col);
System.out.println(String.valueOf(value));
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Forum osFrame = new Forum();
}
});
}
public Forum() {
tableModel = new MyTableModel();
dialogTable = new JTable(tableModel) {
private static final long serialVersionUID = 1L;
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
JComponent jc = (JComponent) comp;//for Custom JComponent
if (!isRowSelected(row)) {
int modelRow = convertRowIndexToModel(row);
boolean type = (Boolean) getModel().getValueAt(modelRow, 2);
boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3);
comp.setForeground(Color.black);
if ((type) && (!type1)) {
comp.setBackground(clr1);
} else if ((!type) && (type1)) {
comp.setBackground(Color.orange);
} else if ((!type) || (!type1)) {
comp.setBackground(Color.red);
} else {
comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker());
}
dialogTable.convertRowIndexToView(0);
} else {
comp.setForeground(Color.blue);
}
if (!isCellEditable(row, column)) {
comp.setForeground(Color.red);
comp.setBackground(Color.magenta);
}
return comp;
}
};
tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tableScroll.setBorder(null);
dialogTable.getTableHeader().setReorderingAllowed(false);
dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lsDialog = dialogTable.getSelectionModel();
dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
dialogTable.setRowHeight(20);
dialogTable.setRowMargin(2);
dialogTable.setPreferredScrollableViewportSize(dialogTable.getPreferredSize());
ListSelectionModel rowSelMod = dialogTable.getSelectionModel();
//ListSelectionModel colSelMod = dialogTable.getColumnModel().getSelectionModel();
rowSelMod.addListSelectionListener(this);
//colSelMod.addListSelectionListener(this);
fatherCenter = new JPanel();
fatherCenter.setLayout(new BorderLayout(10, 10));
fatherCenter.add(tableScroll, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout(10, 10));
frame.add(fatherCenter);
frame.setPreferredSize(new Dimension(400, 660));
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
addData();
}
private class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private Vector<Vector<Object>> _data;
private Vector<String> _colNames;
private boolean[] _columnsVisible = {true, true, true, true, true};
public MyTableModel() {
_colNames = new Vector<String>();
_data = new Vector<Vector<Object>>();
}
public MyTableModel(Vector<String> colnames) {
_colNames = colnames;
_data = new Vector<Vector<Object>>();
}
public void resetTable() {
_colNames.removeAllElements();
_data.removeAllElements();
}
public void setColumnNames(Vector<String> colNames) {
_colNames = colNames;
fireTableStructureChanged();
}
public void addRow(Vector<Object> data) {
_data.add(data);
fireTableRowsInserted(_data.size() - 1, _data.size() - 1);
}
public void removeRowAt(int row) {
_data.removeElementAt(row);
fireTableRowsDeleted(row - 1, _data.size() - 1);
}
#Override
public int getColumnCount() {
return _colNames.size();
}
#Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return Integer.class;
case 1:
return Double.class;
case 2:
return Boolean.class;
case 3:
return Boolean.class;
default:
return String.class;
}
}
#Override
public boolean isCellEditable(int row, int colNum) {
switch (colNum) {
case 2:
return false;
default:
return true;
}
}
#Override
public String getColumnName(int colNum) {
return _colNames.get(colNum);
}
#Override
public int getRowCount() {
return _data.size();
}
#Override
public Object getValueAt(int row, int col) {
Vector<Object> value = _data.get(row);
return value.get(col);
}
#Override
public void setValueAt(Object newVal, int row, int col) {
Vector<Object> aRow = _data.elementAt(row);
aRow.remove(col);
aRow.insertElementAt(newVal, col);
fireTableCellUpdated(row, col);
}
public void setColumnVisible(int index, boolean visible) {
_columnsVisible[index] = visible;
fireTableStructureChanged();
}
}
}
Your problem in getColumnClass method as you see you also return Object because of that you also get String columns.
You can determine that method in next way:
#Override
public Class<?> getColumnClass(int arg0) {
return longValues[arg0].getClass();
}
Or return Classes for your columns in another way. But you must to determine this Classes while cunstruct your model.
I have a jtable that has a edit button, when i select a row and clicked to edit button and edit fields, and click to save button, that row doesn't update, And i have to refresh my table to Change that row!
My code:
if (e.getSource() == editButton) {
selectedRow = uTable.getSelectedRow();
if (selectedRow >= 0) {
editUser(selectedRow);
} else {
JOptionPane.showMessageDialog(null, "Select a row");
}
}
public void editUser(int row) {
UserInformation userInf = userModel.getSelectedMember(row);
NewUserFrame_Edit edit = new NewUserFrame_Edit(userInf, row);
}
...
My NewUserFrame_Edit Class :
public class NewUserFrame_Edit extends javax.swing.JFrame {
private AllUser userModel;
private int selectedrow;
private String gender;
public NewUserFrame_Edit(AllUser userModel,UserInformation userinf, int row) {
...
this.userModel = userModel;
jTextField1.setText(userinf.getFname().toString().trim());
jTextField2.setText(userinf.getLname().toString().trim());
if (userinf.getGender().equals("Male")) {
jRadioButton1.setSelected(true);
} else {
jRadioButton2.setSelected(true);
}
jTextField3.setText(userinf.getDate());
selectedrow = row;
setVisible(true);
}
private void updateButtonActionPerformed(java.awt.event.ActionEvent evt) {
userinf = new UserInformation();
userinf.setFname(jTextField1.getText());
userinf.setLname(jTextField2.getText());
userinf.setGender(gender);
userinf.setDate(jTextField3.getText());
userModel.setValueAt(userinf.getFname() , selectedrow, 1);
userModel.setValueAt(userinf.getLname() , selectedrow, 2);
userModel.setValueAt(userinf.getGender(), selectedrow , 3);
userModel.setValueAt(userinf.getDate() , selectedrow, 4);
userModel.updateFile(userModel.Udata);
NewUserFrame_Edit.this.dispose();
}
...
}
My setValueAt() and updateFile() methods of my model Class:
public class AllUser extends AbstractTableModel {
...
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
UserInformation userInfo = Udata.get(rowIndex);
switch (columnIndex) {
case 0:
userInfo.setID((String) value);
break;
case 1:
userInfo.setFname((String) value);
break;
case 2:
userInfo.setLname((String) value);
break;
case 3:
userInfo.setGender((String) value);
break;
case 4:
userInfo.setDate((String) value);
break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
public void updateFile(ArrayList<UserInformation> data) {
PrintWriter pw;
try {
pw = new PrintWriter(new FileWriter("AllUserRecords.txt"));
for (UserInformation userinf : data) {
String line = userinf.getID()
+ " " + userinf.getFname()
+ " " + userinf.getLname()
+ " " + userinf.getGender()
+ " " + userinf.getDate();
pw.println(line);
}
pw.close();
} catch (IOException ioe) {
}
}
...
}
When i select a row and click to edit button, a new jframe is open that its text field is fill with older data, and i update data and click to save button.
Thus, my column is not certain.
I select a entire row, Not a cell!
Thanks.
For changing JTable entries, use TableModel#setValueAt. Calling fireTableDataChanged is unnecessary. This is for use internally within TableModel itself.
if (selectedRow >= 0) {
...
userModel.setValueAt(newValue, selectedRow, 0);
// ... more values for columns 1, 2, 3, etc.
} ...
You can create a method called updateRow(int index,String[] values) within your AbstractModel extending class and within it set new Value for each cell for that row using setValueAt(newValue,row,index). And within overridden setValue method of TableModel write fireTableCellUpdated(row, col).
Consider the Code Given below. Look at the updateRow and setValueAt method in MyModel class. And watch ((MyModel)myModel).updateRow(row,values);//update row written in MyMouseAdapter class.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
class TableRowEdit extends JFrame
{
private JTable table;
private JScrollPane jsPane;
private TableModel myModel;
private JPanel dialogPanel;
private JTextField tf[];
private JLabel lbl[];
public void prepareAndShowGUI()
{
myModel = new MyModel();
table = new JTable(myModel);
jsPane = new JScrollPane(table);
table.getColumnModel().getColumn(2).setCellRenderer(new LabelCellRenderer());
table.addMouseListener(new MyMouseAdapter());
getContentPane().add(jsPane);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
prepareDialogPanel();
pack();
setVisible(true);
}
private void prepareDialogPanel()
{
dialogPanel = new JPanel();
int col = table.getColumnCount() - 1;
dialogPanel.setLayout(new GridLayout(col,2));
tf = new JTextField[col];
lbl = new JLabel[col];
for (int i = 0; i < col; i++)
{
lbl[i] = new JLabel(table.getColumnName(i));
tf[i] = new JTextField(10);
dialogPanel.add(lbl[i]);
dialogPanel.add(tf[i]);
}
}
private void populateTextField(String[] s)
{
for (int i = 0 ; i < s.length ; i++ )
{
tf[i].setText(s[i]);
}
}
public class LabelCellRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table,Object oValue, boolean isSelected, boolean hasFocus, int row, int column)
{
Component c = super.getTableCellRendererComponent(table, oValue,isSelected, hasFocus,row, column);
String value = (String)oValue;
JLabel label =(JLabel)c;
label.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
label.setBackground(Color.lightGray);
label.setHorizontalTextPosition(SwingUtilities.CENTER);
label.setHorizontalAlignment(SwingUtilities.CENTER);
label.setText(value);
return label;
}
}
private class MyMouseAdapter extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent evt)
{
int x = evt.getX();
int y = evt.getY();
int row = table.rowAtPoint(new Point(x,y));
int col = table.columnAtPoint(new Point(x,y));
if (col == 2)
{
String arr[] = new String[table.getColumnCount() - 1];
for (int i = 0 ; i < arr.length ; i++)
{
arr[i] = (String)table.getValueAt(row,i);
}
populateTextField(arr);
JOptionPane.showMessageDialog(TableRowEdit.this,dialogPanel,"Information",JOptionPane.INFORMATION_MESSAGE);
String[] values = new String[tf.length];
for (int i = 0 ; i < tf.length ; i++)
{
values[i] = tf[i].getText();
}
((MyModel)myModel).updateRow(row,values);//update row
}
}
}
private class MyModel extends AbstractTableModel
{
String[] columns = {
"Roll No.",
"Name",
"Action"
};
String[][] inData = {
{"1","Anthony Hopkins","Edit"},
{"2","James William","Edit"},
{"3","Mc. Donald","Edit"}
};
#Override
public void setValueAt(Object value, int row, int col)
{
inData[row][col] = (String)value;
fireTableCellUpdated(row,col);
}
#Override
public Object getValueAt(int row, int col)
{
return inData[row][col];
}
#Override
public int getColumnCount()
{
return columns.length;
}
#Override
public int getRowCount()
{
return inData.length;
}
#Override
public String getColumnName(int col)
{
return columns[col];
}
#Override
public boolean isCellEditable(int row ,int col)
{
return true;
}
//This method updates the Row of table
public void updateRow(int index,String[] values)
{
for (int i = 0 ; i < values.length ; i++)
{
setValueAt(values[i],index,i);
}
}
}
public static void main(String st[])
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
TableRowEdit td = new TableRowEdit();
td.prepareAndShowGUI();
}
});
}
}
UPDATE
Everything was fine with your original code. Keep the code as it was initially. The only problem was line userModel = new AllUser(); in method updateButtonActionPerformed. It was creating new object of AllUser instead of using the current one. So you should remove this line from updateButtonActionPerformed . and change the NewUserFrame_Edit constructor as follows:
public NewUserFrame_Edit(AllUser userModel/*Add this parameter*/,UserInformation userinf, int row) {
...
this.userModel = userModel;
jTextField1.setText(userinf.getFname().toString().trim());
jTextField2.setText(userinf.getLname().toString().trim());
if (userinf.getGender().equals("Male")) {
jRadioButton1.setSelected(true);
} else {
jRadioButton2.setSelected(true);
}
jTextField3.setText(userinf.getDate());
selectedrow = row;
setVisible(true);
}
change your as updateButtonActionPerformed follows:
private void updateButtonActionPerformed(java.awt.event.ActionEvent evt) {
//userModel = new AllUser();//Comment it.
userinf = new UserInformation();
userinf.setFname(jTextField1.getText());
userinf.setLname(jTextField2.getText());
userinf.setGender(gender);
userinf.setDate(jTextField3.getText());
userModel.setValueAt(userinf.getFname() , selectedrow, 1);
userModel.setValueAt(userinf.getLname() , selectedrow, 2);
userModel.setValueAt(userinf.getGender(), selectedrow , 3);
userModel.setValueAt(userinf.getDate() , selectedrow, 4);
userModel.updateFile(userModel.Udata);
NewUserFrame_Edit.this.dispose();
}
And changeeditUser(int row) method of class UserPage as follows:
public void editUser(int row)
{
UserInformation userInf = userModel.getSelectedMember(row);
NewUserFrame_Edit edit = new NewUserFrame_Edit(userModel,userInf, row);
}
Here is your updateFile methd:
public void updateFile(ArrayList<UserInformation> data) {
PrintWriter pw;
try {
pw = new PrintWriter(new FileWriter("AllUserRecords.txt"));
for (UserInformation userinf : data) {
String line = userinf.getID()
+ " " + userinf.getFname()
+ " " + userinf.getLname()
+ " " + userinf.getGender()
+ " " + userinf.getDate();
pw.println(line);
}
pw.close();
} catch (IOException ioe) {
}
}
Another way to implement changes through JTable is to use the code template below:
table.getModel().addTableModelListener(new TableModelListener(){
/**
* Called when table has been changed.
*/
#Override
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel) e.getSource();
String newdata = (String) model.getValueAt(row, column);
model.setValueAt(newdata, row, column);
// do your update with the newdata variable.
}
});
Here you can use the actual event to get the row and column of the cell that has been changed in the JTable variable.
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