Is it possible to separate the jtable model to 5 different models? - java

I create my table model and now i want to seperate it and show it in different JTables. What is the best way to do that?
Here is what i tried :
public List<DefaultTableModel> getProcedures(JPanel panel) {
Object[] data = new Object[blueprint.size()];
Object[] dur = new Object[blueprint.size()]
Object[] status = new Object[blueprint.size()];
List<DefaultTableModel> parralelList = new ArrayList<DefaultTableModel>();
int counter = 0;
for (Object i : blueprint.keySet()) {
data[counter] = blueprint.get(i);
int intDuration = Math.round(blueprintparse.getDuration(i.toString()));
dur[counter] = Integer.toString(intDuration) + "min";
status[counter] = dScreen.fillTableStatus(data[counter].toString());
counter++;
}
parralelList.add(seperateworkFlows(data, dur, status));
return parralelList;
}
private DefaultTableModel seperateworkFlows(Object[] data, Object[] dur, Object[] status) {
DefaultTableModel listModel = new DefaultTableModel();
listModel.addColumn("Procedures", data);
listModel.addColumn("Duration", dur);
listModel.addColumn("Status", status);
return listModel;
}
...
DefaultTableModel model1 = execution.getProcedures(jProgressFlow1).get(0);
jTableFlow1.setModel(model1);
The blueprint is from parsing a json file so from there i am getting the data, duration and status.
Now i want to seperate the model that i created to 5 models under some condition that are inside the json file but at first place i want to hear your opinion also, if the approach is correct.
Thank you very much for your time

Here is my approach.
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
/**
* Table model which allows to split another table model in 2 table models.
*
* #author smedvynskyy
*/
public class SplitTableModel implements TableModel, TableModelListener {
/** Delegate table model. */
private final TableModel delegate;
/** Column index used to split the model. */
private final int splitColumn;
/**
* Part of table to represent (leading [0, {#link #splitColumn}), or trailing [{#link #splitColumn}, delegate.getColumnCount() -
* splitColumn)).
*/
private final boolean leading;
private final Collection<TableModelListener> listeners = new LinkedHashSet<>();
/**
* Instantiates a new split table model.
*
* #param delegate the delegate model to split.
* #param splitColumn the split position (column).
* #param leading defines the part of table to represent (leading: [0, {#link #splitColumn}), or trailing: [{#link #splitColumn},
* delegate.getColumnCount() - splitColumn)).
*/
public SplitTableModel(TableModel delegate, int splitColumn, boolean leading) {
this.delegate = delegate;
this.splitColumn = splitColumn;
this.leading = leading;
delegate.addTableModelListener(this);
}
/**
* Splits the table model in 2 table models.
*
* #param toSplit table model to be split.
* #param splitColumn split column.
* #return array of two models which split the given one (first is the left model, second is the right).
*/
public static TableModel[] split(TableModel toSplit, int splitColumn) {
return new TableModel[] {new SplitTableModel(toSplit, splitColumn, true), new SplitTableModel(toSplit, splitColumn, false)};
}
#Override
public int getRowCount() {
return delegate.getRowCount();
}
#Override
public int getColumnCount() {
return leading ? Math.min(splitColumn, delegate.getColumnCount()) : Math.max(0, delegate.getColumnCount() - splitColumn);
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return delegate.getValueAt(rowIndex, toModelColumnIndex(columnIndex));
}
#Override
public void addTableModelListener(TableModelListener l) {
listeners.add(l);
}
#Override
public void removeTableModelListener(TableModelListener l) {
listeners.remove(l);
}
/**
* Gets all the registered listeners (as unmodifiable collection.
*
* #return all the registered listeners.
*/
public Collection<TableModelListener> getModelListeners() {
return Collections.unmodifiableCollection(listeners);
}
#Override
public String getColumnName(int columnIndex) {
return delegate.getColumnName(toModelColumnIndex(columnIndex));
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return delegate.getColumnClass(toModelColumnIndex(columnIndex));
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return delegate.isCellEditable(rowIndex, toModelColumnIndex(columnIndex));
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
delegate.setValueAt(aValue, rowIndex, toModelColumnIndex(columnIndex));
}
#Override
public void tableChanged(TableModelEvent e) {
int col = e.getColumn() == -1 ? e.getColumn() : toSplitColumnIndex(e.getColumn());
TableModelEvent evt = new TableModelEvent(this, e.getFirstRow(), e.getLastRow(), col, e.getType());
listeners.forEach(l -> l.tableChanged(evt));
}
/**
* Gets the delegate table model.
*
* #return delegate table model.
*/
public TableModel getDelegate() {
return delegate;
}
private int toSplitColumnIndex(int columnIndex) {
return leading ? columnIndex : columnIndex - splitColumn;
}
private int toModelColumnIndex(int columnIndex) {
return leading ? columnIndex : columnIndex + splitColumn;
}
}
This class allows to split a table model in two submodels. But you can continue split, and provide split in 5 models. For example, you have a table model with 15 columns:
TableModel myModel = ...;
List<TableModel> resultModels = new ArrayList<>(5);
TableModel[] split = SplitTableModel.split(myModel, 3);
for (int i = 0; i < 4; i++) {
resultModels.add(split[0]);
if (i == 3) {
resultModels.add(split[1]);
} else {
split = SplitTableModel.split(split[1], 3);
}
}

Related

Can't construct a JTable with int[][] and String[] arguments

The constructor JTable is giving me an error that says:
"The constructor JTable(int[][], String[]) is undefined"
although it has a constructor JTable(Object[][], Object[]) (Calcul.apartements is of the type int[][])
String[] colonnes = {"Appartements", "Prix Milion de Cts", "Tempd duTrajet/C.v (en min)", "Superficie (en m2)", "Etage"};
table = new JTable(Calcul.appartements, colonnes);
You have two choices:
alter your Calcul.appartements data to be Object[][] or Integer[][] (as mentioned by #MadProgrammer in the comments)
Implement your own table model.
Implementing the table model might be as simple as:
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() { return colonnes.length; }
public String getColumnName(int col) { return colonnes[col]; }
public int getRowCount() { return Calcul.appartements.length; }
public Object getValueAt(int row, int col) { Calcul.appartements[row][col]; }
};
JTable table = new JTable(dataModel);

putting data into array and then JTable

Referring to an earlier question i asked
lining up data in console output java
I wish to put my output in an array so that i can then further put this into a JTable
The extract for my code so far is, i am currently printing out the output to the console.
String assd = null;
String eventy = null;
String assdFT = null;
for (int i = 0; i < list.getLength(); i++) {
Element element = (Element)list.item(i);
String nodeName = element.getNodeName();
switch (nodeName) {
case "assd":
assd = element.getChildNodes().item(0).getNodeValue();
break;
case "eventy":
eventy = element.getChildNodes().item(0).getNodeValue();
break;
case "assdFT":
assdFT = element.getChildNodes().item(0).getNodeValue();
break;
System.out.printf("%-30s %-20s %s%n", assd, eventy,assdFT);
Object[][] data = {{assd, eventy,assdFT}};//this only appears to put the elements in row 1, since System.out.println(data[1][0]) causes an out of array exception but System.out.println(data[0][0]) prints out all the elements of assd
To put data directly into a JTable pass an instance of your custom AbstractTableModel to the JTable constructor. Within TableModel, you can define what data is displayed and how it is accessed.
It would probably look something like this:
public class HeaderTableModel extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 8974549762036798969L;
private Object[][] myData;
public HeaderTableModel(final Object[][] theRows) {
myHeaderRows = theRows;
}
/*
* (non-Javadoc)
*
* #see javax.swing.table.TableModel#getColumnCount()
*/
#Override
public int getColumnCount() {
return LocalStorage.getNumColumns();
}
/*
* (non-Javadoc)
*
* #see javax.swing.table.TableModel#getRowCount()
*/
#Override
public int getRowCount() {
return LocalStorage.getNumRows();
}
/*
* (non-Javadoc)
*
* #see javax.swing.table.TableModel#getValueAt(int, int)
*/
#Override
public Object getValueAt(final int theRow, final int theColumn) {
return myHeaderRows[theRow][theColumn];
}

JTable, refreshing rowData vector in static context

i've declared a JTable (inside a class extended JPanel constructor) such as
data_table = new JTable(info, header) {
#Override
public boolean isCellEditable(int row, int column) {
//disable table editing
return false;
}
};
where info and column are declared
static String[][] info = new String[row][cols];
static String[] header = {"h1", "h2", "h3"};
Now i need to update, when some events occours, the table content by invoke a static method. How can i do it?
i don't have a tableModel, i've a matrix of string
All tables use a TableModel. When you create the table the matrix of Strings is used by the TableModel.
To update your data you do something like:
table.setValueAt(...);
This will cause the model to be updated and the model will tell the table to repaint itself.
Read the Swing tutorial on How to Use Tables for more information about tables.
Also, you should NOT be using static variables or method. If you are then you program is poorly designed. Again read the tutorial for a better example of how to structure your code.
If you want to notify your JTable about changes of your data, call a method on your tablemodel that will update the data and call fireTableDataChanged()
Its is a good practice to use a JTableModel to maintain your data inside the JTable.
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html
And that is your tablemodel that will fire the fireTableDataChanged() when value will change.
class MyTableModel extends AbstractTableModel {
private String[] columnNames = ...//same as before...
private Object[][] data = ...//same as before...
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();
}
/*
* 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) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
...
}

Issues with an Array in an ArrayList, Java

I created a multidimensional array called current_map.
I am trying to access current_map:
current_map[0][1]
However I receive the error:
error: array required, but String found
Here is my code for your viewing pleasure
import java.util.*;
import java.util.Map.Entry;
import java.util.ArrayList;
public class TestApp {
private ArrayList<String[]> current_map = new ArrayList<String[]>();
public TestApp() {
current_map.add(new String[] { "0","0","0" });
current_map.add(new String[] { "0","Q","0" });
current_map.add(new String[] { "0","0","0" });
}
public String getValue(int X,int Y){
String[] obj_map = current_map.toArray(new String[current_map.size()]);
return obj_map[X][Y]; // for example, getValue(2,2), should give "Q"
}
}
How can I stop this issue?
You can do something like this:
import java.util.*;
import java.util.Map.Entry;
import java.util.ArrayList;
public class TestApp {
private ArrayList<String[]> current_map = new ArrayList<String[]>();
public TestApp() {
current_map.add(new String[] { "0","0","0" });
current_map.add(new String[] { "0","Q","0" });
current_map.add(new String[] { "0","0","0" });
}
public String getValue(int X,int Y){
return current_map.get(Y)[X]; // for example, getValue(2,2), should give "Q"
}
public static void main(String[] args) {
TestApp ta = new TestApp();
System.out.println(ta.getValue(1, 1));
}
}
Note that in Java array indexes are 0-based, so 2nd row, 2nd column is represented with (1, 1), not (2, 2).
Hope this helps.
Unless there's compelling reason to do a full copy on every get command, you should use your existing structure.
public String getValue(int X, int Y)
{
return current_map.get(X)[Y];
}
You have said obj_map is a String[], but in the very next line you treat it as a 2D array.
What you have is not really a true multi-dimension representation as the way you access different dimensions is not consistent. Its semantics but to call it a true multi-dimensional (including symantics) you need something like this (Please refer this for the source of this code. I am not the owner of this code.)
import java.util.ArrayList;
public class ArrayList2d<Type>
{
ArrayList<ArrayList<Type>> array;
public ArrayList2d()
{
array = new ArrayList<ArrayList<Type>>();
}
/**
* ensures a minimum capacity of num rows. Note that this does not guarantee
* that there are that many rows.
*
* #param num
*/
public void ensureCapacity(int num)
{
array.ensureCapacity(num);
}
/**
* Ensures that the given row has at least the given capacity. Note that
* this method will also ensure that getNumRows() >= row
*
* #param row
* #param num
*/
public void ensureCapacity(int row, int num)
{
ensureCapacity(row);
while (row < getNumRows())
{
array.add(new ArrayList<Type>());
}
array.get(row).ensureCapacity(num);
}
/**
* Adds an item at the end of the specified row. This will guarantee that at least row rows exist.
*/
public void add(Type data, int row)
{
ensureCapacity(row);
while(row >= getNumRows())
{
array.add(new ArrayList<Type>());
}
array.get(row).add(data);
}
public Type get(int row, int col)
{
return array.get(row).get(col);
}
public void set(int row, int col, Type data)
{
array.get(row).set(col,data);
}
public void remove(int row, int col)
{
array.get(row).remove(col);
}
public boolean contains(Type data)
{
for (int i = 0; i < array.size(); i++)
{
if (array.get(i).contains(data))
{
return true;
}
}
return false;
}
public int getNumRows()
{
return array.size();
}
public int getNumCols(int row)
{
return array.get(row).size();
}
}

Use String list as source of Combo Box

I wanted to use a String list as a source of various options in jComboBox in Java. Can you tell which method to use
Thanks
See Below for my answer... take into account this is untested and merely an example.
You need to create a custom implmentation of ComboBoxModel like Chandru said,
Then set the ComboBoxModel on your JComboBox using the setModel() method and add elements using ((CustomComboBoxModel<String>)jComboBox.getModel()).add(listOfThings);
Something like this:
import java.util.List;
import javax.swing.ComboBoxModel;
/**
* Custom Implementation of {#code ComboBoxModel} to allow adding a list of
* elements to the list.
*/
public interface CustomComboBoxModel<T> extends ComboBoxModel {
void add(List<T> elementsToAdd);
List<T> getElements();
}
and then implement the interface using something like this:
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractListModel;
/**
* Default Implementation of CustomComboBoxModel - untested.
*/
public class DefaultCustomComboBoxModel<T> extends AbstractListModel implements CustomComboBoxModel<T> {
List<T> objects;
T selectedObject;
/**
* Constructs an empty DefaultCustomComboBoxModel object.
*/
public DefaultCustomComboBoxModel() {
objects = new ArrayList<T>();
}
/**
* Constructs a DefaultCustomComboBoxModel object initialized with
* an array of objects.
*
* #param items an array of Object objects
*/
public DefaultCustomComboBoxModel(final T items[]) {
objects = new ArrayList<T>();
int i, c;
for (i = 0, c = items.length; i < c; i++) {
objects.add(items[i]);
}
if (getSize() > 0) {
selectedObject = objects.get(0);
}
}
// implements javax.swing.ComboBoxModel
/**
* Set the value of the selected item. The selected item may be null.
* Make sure {#code anObject} is an instance of T otherwise a
* ClassCastException will be thrown.
* <p>
* #param anObject The combo box value or null for no selection.
*/
#Override
public void setSelectedItem(Object anObject) {
if ((selectedObject != null && !selectedObject.equals(anObject))
|| selectedObject == null && anObject != null) {
selectedObject = (T) anObject;
fireContentsChanged(this, -1, -1);
}
}
// implements javax.swing.ComboBoxModel
#Override
public T getSelectedItem() {
return selectedObject;
}
// implements javax.swing.ListModel
#Override
public int getSize() {
return objects.size();
}
// implements javax.swing.ListModel
#Override
public T getElementAt(int index) {
if (index >= 0 && index < objects.size()) {
return objects.get(index);
} else {
return null;
}
}
/**
* Returns the index-position of the specified object in the list.
*
* #param anObject
* #return an int representing the index position, where 0 is
* the first position
*/
public int getIndexOf(T anObject) {
return objects.indexOf(anObject);
}
// implements javax.swing.MutableComboBoxModel
public void addElement(T anObject) {
objects.add(anObject);
fireIntervalAdded(this, objects.size() - 1, objects.size() - 1);
if (objects.size() == 1 && selectedObject == null && anObject != null) {
setSelectedItem(anObject);
}
}
// implements javax.swing.MutableComboBoxModel
public void insertElementAt(T anObject, int index) {
objects.add(index, anObject);
fireIntervalAdded(this, index, index);
}
// implements javax.swing.MutableComboBoxModel
public void removeElementAt(int index) {
if (getElementAt(index) == selectedObject) {
if (index == 0) {
setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1));
} else {
setSelectedItem(getElementAt(index - 1));
}
}
objects.remove(index);
fireIntervalRemoved(this, index, index);
}
// implements javax.swing.MutableComboBoxModel
public void removeElement(T anObject) {
int index = objects.indexOf(anObject);
if (index != -1) {
removeElementAt(index);
}
}
/**
* Empties the list.
*/
public void removeAllElements() {
if (objects.size() > 0) {
int firstIndex = 0;
int lastIndex = objects.size() - 1;
objects.clear();
selectedObject = null;
fireIntervalRemoved(this, firstIndex, lastIndex);
} else {
selectedObject = null;
}
}
#Override
public void add(List<T> elementsToAdd) {
objects.addAll(elementsToAdd);
fireContentsChanged(this, -1, -1);
}
#Override
public List<T> getElements() {
return objects;
}
}
Extend DefaultComboboxModel and create a method which takes a Collection and sets the items from that collection. Set this custom model as your combobox's model using setModel().
Here you have code which creates combo box from array of Strings, all you need to do is transform your list to an array.
String petStrings = ...;
//Create the combo box, select item at index 4.
//Indices start at 0, so 4 specifies the pig.
JComboBox petList = new JComboBox(petStrings.toArray());
The easiest way is:
comboBox.setModel(new DefaultComboBoxModel(list.toArray()));
I know it's an old post, but I wanted to make a small addition to edwardsmatt's DefaultCustomComboBoxModel. Don't forget to add this constructor:
public DefaultCustomComboBoxModel(List<T> list) {
objects = list;
if (getSize() > 0) {
selectedObject = objects.get(0);
}
}
so that the model can also be initialized with a list, e.g.
myCombo.setModel(new DefaultCustomComboBoxModel(myList));
If you use ((CustomComboBoxModel)myCombo.getModel()).add(myList) you'll need to explicitly set the selected item.
You can also do it like this:
DefaultTableModel modelTabele = (DefaultTableModel) tblOsobe.getModel();
modelTabele.addColumn("Ime");
modelTabele.addColumn("Prezime");
modelTabele.addColumn("Datum Rodjenja");
for (Osoba osoba : Liste.osobe) {
System.out.println("" + osoba);
Object[] podaci = new Object[3];
podaci[0] = osoba.getIme();
podaci[1] = osoba.getPrezime();
podaci[2] = osoba.getDatumRodjenja();
modelTabele.addRow(podaci);
}
This model has 3 columns and as many rows as there are in Liste.osobe list of strings.

Categories