I have a ArrayList<String[]> data which I place values into at a different point in the program, I have made it a variable of MyTable which extends AbstractTableModel. But I don't know how to place it into the table.
I have previously put a String[][] into the table, but I am not sure how that would work with ArrayList class.
For getRowCount() I can do newStringArr.length and for getColumnCount I can do newStringArr[0].length and for getValueAt(int row, int column) I can return newStringArr[row][column] for a String[][] type. What would be the equal of those functions for an ArrayList?
Here is a good example using AbstractTableModel.
In your case, MyTable can be defined as:
class MyTable extends AbstractTableModel {
private final int numRows;
private final int numColumns;
private List<String[]> data = new ArrayList<String[]>();
public MyTable(int numColumns, int numRows) {
this.numColumns = numColumns;
this.numRows = numRows;
init();
}
public int getColumnCount() {
return data.get(0).length;
}
public int getRowCount() {
return data.size();
}
public Optional<String> getValueAt(int row, int col) {
if(isNotValidEntry(row, col)) {
throw new RuntimeException("Out of bound row or col");
}
return Optional.ofNullable(data.get(row - 1)[col -1]);
}
public void setValueAt(String value, int row, int col) {
if(isNotValidEntry(row, col)) {
throw new RuntimeException("Out of bound row or col");
}
data.get(row - 1)[col - 1] = value;
fireTableCellUpdated(row, col);
}
private void init() {
IntStream.range(0, numRows)
.forEach(r -> data.add(new String[numColumns]));
}
private boolean isNotValidEntry(int row, int col) {
return numRows <= row - 1 || numColumns <= col - 1;
}
}
Related
can anybody here help me on how to compute rows in jtable?
assuming that i have a table containing fields date, description, aCCount, SCount and lost , i have loaded the four field from database except lost field because i want to compute it on runtime, can anybody help me? here is image attach for clarification
public void cha(){
ArrayList<Chalsim> list = getChalsim();
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
Object[] row = new Object[4];
for(int i =0; i<list.size(); i++){
row[0] = list.get(i).getDate();
row[1] = list.get(i).getDesc();
row[2] = list.get(i).getAc();
row[3] = list.get(i).getSc();
model.addRow(row);
}
}
You can extend AbstractTableModel,and then assign it to JTable
new AbstractTableModel() {
public String getColumnName(int col) {
return columnNames[col].toString();
}
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int row, int col) {
return rowData[row][col];
}
public boolean isCellEditable(int row, int col)
{ return true; }
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
}
and then put it into JTable
JTable table = new JTable(new MyTableModel());
I have a JTable with 10 columns headers: "A","d","e","f","B","g","h","C","i","j".I want in first view JTable Show only "A","B","C" and I have two JButton when clicked on ViewAll Button all columns show and when clicked on hide Jtable show only three columns with "A","B","C" headers.how can do it?my GridTableModel is:
public abstract class GridTableModel<T> extends AbstractTableModel {
private static final long serialVersionUID = 4283080272635443348L;
private List<T> rows = new ArrayList<T>();
/**
* The property used to find real index of rows that currently are shown to user.
*/
private int offset;
public abstract String[] getColumnNames();
#Override
public String getColumnName(int column) {
return getColumnNames()[column];
}
#Override
public int getColumnCount() {
return getColumnNames().length;
}
#Override
public int getRowCount() {
return rows == null ? 0 : rows.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rows.size() > 0) {
return getValueAt(rows.get(rowIndex), rowIndex, columnIndex);
}
return null;
}
public void setData(List<T> results, int offset) {
this.rows = results;
this.offset = offset;
fireTableDataChanged();
}
public T get(int row) {
return rows.size() > 0 ? rows.get(row) : null;
}
public abstract Object getValueAt(T t, int rowIndex, int columnIndex);
public List<T> get(int[] rows) {
List<T> list = new ArrayList<T>();
for (int row : rows) {
list.add(this.rows.get(row));
}
return list;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public List<T> getRows() {
return rows;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
if (1==1) {
return Object.class;
}
return getValueAt(0, columnIndex).getClass();
}
}
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.
How can I print three different tables side by side or add them together in one printing? since the following code prints separately and in different pages.
I have little knowledge with the printing aspect of JTable's.
I am using NetBeans 8.0.
Or could I instead import the data to an excel file and print it from there? Is that plausible?
edit: All three tables must be together, side by side when it print, regardless if its portrait or landscape. Even better if all the tables or joined and is represented by multiple columns instead of three separate tables.
PrinterJob job = PrinterJob.getPrinterJob();
PrintRequestAttributeSet asset = new HashPrintRequestAttributeSet();
PageFormat pf = job.pageDialog(asset);
job.setPrintable(new recording_system(), pf);
boolean ok = job.printDialog(asset);
if (ok) {
try {
jTstudents.print(JTable.PrintMode.NORMAL);
jTscores.print(JTable.PrintMode.NORMAL);
jTresults.print(JTable.PrintMode.NORMAL);
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
The tables look like this
Implement a TableModel class that combines all models.
TableModel model = new ParallelTableModel(jTStudents.getModel(),
jTScores.getModel(),
TResults.getModel());
JTable totalTable = new JTable(model);
Copy table header.
And then totalTable.getPrintable for printing.
/**
* Table Model composed from side-by-side table models.
*/
public class ParalleTableModel extends AbstractTableModel {
private final TableModel[] models;
public ParalleTableModel(TableModel... models) {
this.models = models;
}
#Override
public int getRowCount() {
return models[0].getRowCount();
}
#Override
public int getColumnCount() {
int count = 0;
for (TableModel model : models) {
count += model.getColumnCount();
}
return count;
}
#Override
public String getColumnName(int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.getColumnName(columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public Class<?> getColumnClass(int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.getColumnClass(columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.isCellEditable(rowIndex, columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.getValueAt(rowIndex, columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
model.setValueAt(aValue, rowIndex, columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
}
I'm trying to read a csv file and get it setup to convert into another format to save some time at work, but the JTable i'm loading it into throws an exception when a row has a length less than the expected column. Is there a method to create an empty cell if row length < column length?
here is the table model:
private class CSVTableModel extends AbstractTableModel{
private ArrayList<String[]> list;
private String[] columns;
public CSVTableModel() {
this.list = p.getData();
this.columns = p.getHeaders();
}
#Override
public String getColumnName(int col) {
return columns[col];
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public int getColumnCount() {
return columns.length;
}
#Override
public Object getValueAt(int row, int col) {
return list.get(row)[col];
}
#Override
public void setValueAt(Object value, int row, int col) {
list.get(row)[col] = (String) value;
this.fireTableCellUpdated(row, col);
}
}
So you can see with the getValueAt(int row, int col) method it will cause an error if the col exceeds the String[].length.
I literally solved it after posting. Rubber duck debugging.
#Override
public Object getValueAt(int row, int col) {
if ( col < list.get(row).length ) {
return list.get(row)[col];
} else {
return "";
}
}
added a condition and works fine now. Should've seen it before.