I'm making a database management system using java and mySQL. I'm using a jTable as a interface to the database.
Though the post look little long, the problem wont be that much of complex, for an experienced person (i guess).
This is my problem. After selecting a cell, i can enter values, (no prob with that). But after entering values, when i click on some other cell, the entered values get disappeared and it gets back to null.
Can't figure out the reason. I don't have much experience on jTables. But i think the problem is with the tablemodel.
This is my tablemodel
import Templates.TableEntry;
import java.util.LinkedList;
import javax.swing.table.AbstractTableModel;
public class myTableModel extends AbstractTableModel {
public static final int DATE_INDEX = 0;
public static final int ORDERNO_INDEX = 1;
public static final int ROOT_INDEX = 2;
public static final int HIDDEN_INDEX = 3;
public String[] columnnames;
public LinkedList<TableEntry> entryList;
public myTableModel(String[] columnNames) {
this.columnnames = columnNames;
entryList = new LinkedList<TableEntry>();
}
#Override
public String getColumnName(int column) {
return columnnames[column];
}
#Override
public boolean isCellEditable(int row, int column) {
if (column == HIDDEN_INDEX) {
return false;
} else {
return true;
}
}
#Override
public Class getColumnClass(int column) {
return String.class;
}
#Override
public String getValueAt(int row, int column) {
TableEntry record = entryList.get(row);
switch (column) {
case DATE_INDEX:
return record.date;
case ORDERNO_INDEX:
return record.jobOdrerNo;
case ROOT_INDEX:
return record.rootCardNos;
default:
return null;
}
}
public void setValueAt(String value, int row, int column) {
TableEntry record = entryList.get(row);
switch (column) {
case DATE_INDEX:
record.date = value;
break;
case ORDERNO_INDEX:
record.jobOdrerNo = value;
break;
case ROOT_INDEX:
record.rootCardNos = value;
break;
default:
System.out.println("invalid index");
}
updateTable(row, column);
}
public void updateTable(int row, int column) {
fireTableCellUpdated(row, column);
}
#Override
public int getRowCount() {
return entryList.size();
}
#Override
public int getColumnCount() {
return columnnames.length;
}
public boolean hasEmptyRow() {
if (entryList.size() == 0) {
return false;
}
TableEntry entry = entryList.get(entryList.size() - 1);
if ("".equals(entry.date)) {
return true;
} else {
return false;
}
}
public void addEmptyRow() {
entryList.add(new TableEntry());
fireTableRowsInserted(entryList.size() - 1, entryList.size() - 1);
}
public void deleteRow(int i) {
if (i != 0) {
entryList.remove(i);
fireTableRowsDeleted(i - 1, i + 1);
}
}
}
Sorry about the length. But i posted the whole code for the sake of completeness. Most of the parts can be neglected.
TableEntry is a simple class.
package Templates;
public class TableEntry {
public String date;
public String jobOdrerNo;
public String rootCardNos;
public String yardRootCard;
public String MCISO_NO;
public String service_maintenance_breakdown;
public String jobNo;
public String machineName;
public String fault;
public String problematicPart;
public String person;
public String action;
public String startTime;
public String finishedTime;
public String durationOfRepair;
public String spareParts;
public String itemCode;
public String no;
public String value;
public String totalCost;
public String remark;
public String breakdownAndSolution;
}
Hope I've provided all the details. This has been a real bug for me. Any help is appreciated.
Thanx in advance..!
(If any clarification is needed, please let me know.. difficult to post whole project. It's a bit huge.. :D)
There's a small bug in your code. Next time, be carefull..
In the tablemodel's method "setValueAt(---)" you've put wrong arguments. you were trying to override a method of class "AbstractTableModel". Original method is,
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
}
But you've written your method as,
public void setValueAt(String value, int row, int column) {
...//method body
}
Hence, it wont override the intended function. Everytime a cell is changed, tablemodel will call the original "setValueAt(...)" function. But since it hasn't overriden, it will do nothing (you must override it, original method has no body).
Hope this helps..
You can use defaultTableModal for normal use. It has extended abstractTableModal and provide methods for frequently used requirements. Try it first, if not enough, then go develop your own class...
Related
I've run into a very strange issue. I wrote a model for a table and for the most part it works perfect. When I update the row data via the setValueAt function it works and the data in the ArrayList is updated and complete. But when i run the getTotalPay function the same array is empty and i get a null value exception.
I've rewrote the code a number of different ways and tried a couple of different approaches to the problem but the problem persists. I know i've done something wrong i just cannot figure out what the problem is. After search the net and not finding a solution i'm posting this.
Things i've tried are replacing the variable, putting the data into two different variables.
Here is the model
public class WeeklyWagesModel extends AbstractTableModel {
private String defaultValue = "Click to edit";
private String[] headings = { "Date From", "Date To", "Wages", "Pay Date" };
private ArrayList<String[]> theData = new ArrayList<String[]>();
public WeeklyWagesModel() {
theData.add(createDefaultRow());
}
#Override
public int getColumnCount() {
return headings.length;
}
public String getColumnName(int col) {
return headings[col];
}
#Override
public int getRowCount() {
return theData.size();
}
#Override
public Object getValueAt(int row, int col) {
return theData.get(row)[col];
}
public boolean isCellEditable(int row, int col) {
return true;
}
public void setValueAt(Object value, int row, int col) {
theData.get(row)[col] = String.valueOf(value);
if (row == (theData.size() - 1)) {
theData.add(createDefaultRow());
}
fireTableDataChanged();
}
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
public ArrayList<String[]> getData() {
return theData;
}
public String getTotalPay() {
System.out.println("Total Pay: " + theData.size());
BigDecimal total = BigDecimal.ZERO;
for (String[] eachRow : theData) {
if (StringUtils.isNumeric(eachRow[2])) {
total.add(new BigDecimal(eachRow[2]));
}
}
return NumberFormat.getCurrencyInstance().format(total);
}
public String getTotalWeeks() {
return "";
}
private String[] createDefaultRow() {
String[] newRow = new String[headings.length];
for (int i = 0; i < newRow.length; i++) {
newRow[i] = defaultValue;
}
return newRow;
}
}
I am having a strange error when I am trying to remove selected node from JTreeTable.
First of all, I get selected row in my main class from JXtreeTable
table.getSelectedRow()
I do it with this method, and it returns me a correct number of row.
But then, shit happends.
In my model class I call method delete children:
package JTreeTable;
import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.jdesktop.swingx.treetable.MutableTreeTableNode;
import org.jdesktop.swingx.treetable.TreeTableModel;
public class TableModel extends DefaultTreeTableModel implements TreeTableModel {
DefaultMutableTreeTableNode root;// = new DefaultMutableTreeTableNode("Root");
public TableModel(DefaultMutableTreeTableNode root){
super(root);//it didnt work without this line. it took me a day to figure it out. I hate my life sometimes.
this.root = root;
}
public int getColumnCount()
{
return 4;
}
#Override
public String getColumnName( int column )
{
switch( column )
{
case 0: return "Description";
case 1: return "Amount";
case 2: return "Date";
case 3: return "Paid";
default: return "Unknown";
}
}
public void addChildren(){
int rootChildCount = root.getChildCount();
ArrayNode newChild = new ArrayNode(new Object[] {"dfds", "sfddsf","dfsfsd","fdsfsd"});
this.insertNodeInto(newChild, root, rootChildCount);
}
public void removeChildren(int index){
//root.remove(index);
System.out.println(root.getChildCount());
}
}
And here my node class:
package JTreeTable;
import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
public class ArrayNode extends DefaultMutableTreeTableNode {
public ArrayNode(Object[] data) {
super(data);
}
#Override
public Object getValueAt(int column) {
return getUserObject()[column];
}
#Override
public void setValueAt(Object aValue, int column) {
getUserObject()[column] = aValue;
}
#Override
public int getColumnCount() {
return 4;
}
#Override
public Object[] getUserObject() {
return (Object[]) super.getUserObject();
}
#Override
public boolean isEditable(int column) {
return true;
}
}
So, when i use method root.remove(index) i always get error "Node must be a valid node managed by this model". But i am pretty sure my nodes are ok! What this means and is it fixable?
You are trying to remove the child directly from another node, bypassing the TreeTableModel. Use DefaultTreeTableModel.removeNodeFromParent, e.g:
public void removeChildren(int index) {
MutableTreeTableNode node = root.getChildAt(index);
this.removeNodeFromParent(node);
}
I got an AbstractTableModel, like this:
public class TableModelClienteFornecedor extends AbstractTableModel {
private List<ClienteFornecedorDTO> linhas;
private String[] colunas = new String[]{"Nome", "Conta"};
public TableModelClienteFornecedor() {
linhas = new ArrayList<>();
}
#Override
public int getRowCount() {
return linhas.size();
}
#Override
public int getColumnCount() {
return colunas.length;
}
#Override
public String getColumnName(int column) {
return colunas[column];
}
#Override
public Class getColumnClass(int column) {
return (getValueAt(0, column).getClass());
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
ClienteFornecedorDTO cf = linhas.get(rowIndex);
switch (columnIndex) {
case 0:
return cf.getNome();
case 1:
return cf.getConta();
default:
throw new IndexOutOfBoundsException("Coluna incorreta");
}
}
public void clear(JTable table) {
table.setRowSorter(null);
int indiceAntigo = this.getRowCount();
linhas.clear();
int indiceNovo = this.getRowCount();
this.fireTableRowsDeleted(indiceAntigo, indiceNovo);
}
public boolean isEmpty() {
return linhas.isEmpty();
}
public void add(ClienteFornecedorDTO cf) {
linhas.add(cf);
int index = this.getRowCount();
fireTableRowsInserted(index, index);
}
public void addList(List<ClienteFornecedorDTO> list, JTable table) {
int tamanhoAntigo = this.getRowCount();
linhas.addAll(list);
int tamanhoNovo = this.getRowCount() - 1;
this.fireTableRowsInserted(tamanhoAntigo, tamanhoNovo);
table.setAutoCreateRowSorter(true);
}
public ClienteFornecedorDTO get(int i) {
return linhas.get(i);
}
}
And the code below works ok to fill the my Jtable with data:
private void realizarBusca(String nome) {
IContaDAO dao = new ContaDAO();
boolean isFornecedor = radioFornecedor.isSelected();
List<ClienteFornecedorDTO> retorno =
dao.retornaContaClienteFornecedor(isFornecedor, nome);
tableModelClienteFornecedor.clear();
tableModelClienteFornecedor.addList(retorno, tableClienteFornecedor);
tableClienteFornecedor.updateUI();
}
Everything's working fine to me, and when I sort my Jtable visibily it's ok too, the problem is when I click on a specific row from my Jtable after I sorted it, the row it's not updated.
Anyone can help me with that?
I would appreciate, 'cause I'm on it since yesterday and still wasn't able to find a way to solve it.
Look at the methods convertRowIndexToModel() and convertRowIndexToView() in JTable.
When the table is sorted, the indices of the rows in the view don't match with the indices in the model anymore, and you have to use the above methods to convert from index to view and vice-versa.
For example, if you call JTable.getSelectedRow(), you'll get the view index of the selected row. You'll have to convert it to the model index (using convertRowIndexToModel()) to be able to get the selected object from the list in your model.
I'm developing a software for my friend.I have developed 90% of my project and my problem is I have a table which I fill with data in database.I have used a custom table model to fill jtable. It fills data perfectly but the problem is it doesn't contain proper column header instead of that it contain A,B,C for column headers .
here is my custom table model class.
public class SellUpdateModel extends AbstractTableModel
{
private Vector<Vector> data;
public SellUpdateModel(String Jid)
{
data = new Vector<>();
data = new JobDetailsDAO().get_ItemDescriptionAndQuantity(Jid); //Retrive data from databse and fill it to vector.
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return false; // does not allowed to edit cells
}
#Override
public int getRowCount()
{
return data.size();
}
#Override
public int getColumnCount()
{
return 3;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
return data.elementAt(rowIndex).elementAt(columnIndex);
}
public SellUpdateModel deleteRow(int row, Vector pData)
{
data.remove(data.elementAt(row)); // remove a record from vector
data.add(pData); // add a record to vector
return this;
}
}
You have to override getColumnName(int columnIndex).
public class SellUpdateModel extends AbstractTableModel {
private final String[] tableHeaders = {"X", "Y", "Z"};
#Override
public String getColumnName(int columnIndex) {
return tableHeaders[columnIndex];
}
}
I can't figure out something using the constructor JTable(TableModel dm).
I'm using a LinkedList to manage my data so, to display it, I extended AbstractTableModel:
public class VolumeListTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private LinkedList<Directory> datalist;
private Object[] columnNames= {"ID", "Directory", "Wildcard"};
public VolumeListTableModel(){
}
public void setDatalist(LinkedList<Directory> temp){
this.datalist = temp;
}
public LinkedList<Directory> getDatalist(){
return (LinkedList<Directory>) this.datalist.clone();
}
public Object[] getColumnNames() {
return this.columnNames;
}
#Override
public int getColumnCount() {
return Directory.numCols;
}
#Override
public int getRowCount() {
return this.datalist.size();
}
#Override
public Object getValueAt(int row, int col) {
Directory temp = this.datalist.get(row);
switch(col){
case 0:
return temp.getId();
case 1:
return temp.getPath();
case 2:
return temp.getWildcard();
default:
return null;
}
}
I'm doing something wrong because when I run my GUI I get column names labeled A,*B*,C.
There is no method in AbstractTableModel called getColumnNames, so I believe your method is being ignored. The actual method you want to override is the getColumnName method.
Try adding this method to your VolumeListTableModel class
public String getColumnName(int column) {
return columnNames[column];
}
You need to override the getColumnName method which in your case will simply
return columnNames[column];
You have to Override this method :
public String getColumnName(int column)
AbstractTableModel does not have a getColumnNames method, but it is easy to implement:
public class VolumeListTableModel extends AbstractTableModel {
// [...]
public String[] getColumnNames() {
String[] columnNames = new String[this.getColumnCount()];
for (int i = 0, columnCount = this.getColumnCount(); i < columnCount; i++) {
columnNames[i] = this.getColumnName(i);
}
return columnNames;
}
// [...]
}