Arraylist to 2D array and then to a JTable - java

i'm struggeling to make my arraylist into an 2D array and then adding it on a table to show the data.
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public class Planettabell
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame vindu = new Test();
vindu.setVisible(true);
}
});
}
}
class Test extends JFrame
{
private String[] name = {"Name", "grade"};
Object[][] cell = {{"nameHer", "GradeHer"}};
Object[][] cell2 = {{"nameHer2", "gradeHer2"}};
Object[][] cell3 = {{"nameHer3", "gradeHer3"} };
public Test()
{
setTitle("Planettabell");
setSize(500, 210);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
List<Object[]> list = new ArrayList<Object[]>();
list.add(cell);
list.add(cell2);
list.add(cell3);
Object[][]array = list.toArray(new Object[list.size()][]);
JTable tabell = new JTable(array, name);
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(new JScrollPane(tabell), BorderLayout.CENTER);
}
}
i will get this message if i run it
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1
this code is working if i add 'cell' instead of 'array' on JTable, but i need the entire array from list to work.
i have also tried:
int number = list.size()/2;
Object[][] ArrayNew = new Object[number][2];
for(int x = 0; x< number; x++)
{
for(int z = 0; z < 2; z++)
{
int y = 2 * x;
ArrayNew [x][z] = list.get(y+z);
}
}
JTable tabell = new JTable(ArrayNew, name);
instead of list.toarray. But then i only gett [[Ljava.lang.Object;#28864ae7 and [[Ljava.lang.Object;#49214a13 where the text in the table supposed to be.
would appreicate any answer :)

Your list is effectively a 3D data structure (a list of 2D arrays), it should be only 2D (a list of arrays):
Object[] information = {"nameHer", "GradeHer"};
List<Object[]> list = new ArrayList<Object[]>();
list.add(information); // more data here
Object[][]array = list.toArray(new Object[list.size()][]);
In your code, Object[][] cell = {{"nameHer", "GradeHer"}}; is a 2D array, then you add it into a list (making your list 3 dimensionnal in the process).
Your cells shouldn't be 2D, they represent your rows and must be1D arrays.
Replace by Object[] cell = {"nameHer", "GradeHer"}; and it will work

import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public class Planettabell
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame vindu = new Test();
vindu.setVisible(true);
}
});
}
}
class Test extends JFrame
{
private String[] name = {"Name", "grade"};
Object[][] cells = {
{"nameHer", "GradeHer"},
{"nameHer2", "gradeHer2"},
{"nameHer3", "gradeHer3"}
};
public Test()
{
setTitle("Planettabell");
setSize(500, 210);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable tabell = new JTable(cells, name);
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(new JScrollPane(tabell), BorderLayout.CENTER);
}
}

You're approaching this problem entirely wrong.
a DefaultTableModel takes a 2d array and displays everything for you including column headers. So, without seeing the code to your KarakterTabell I can't imagine what more you're trying to achieve.
To do a table model correctly all you need to do is have a means to access your data in an x,y fashion. Then, pass in the data stream into this new model it will run when the table comes up:
public class KarakterTableModel implements TableModel {
List<String[]> data = new ArrayList<String[]>();
public KarakterTableModel(BufferedReader reader) {
while(reader.ready()) {
String columnData = reader.readLine();
String[] columns = columnData.split(" ");
data.add(columns);
}
}
public Object getValueAt(int x, int y) {
String[] row = data.get(x);
return row[y];
}
}
JTable table = new Jtable(new KarakterMode(new BufferedReader(System.in));
Also remember: it's public Object getValueAt() -- the JTable will put the "toString()" call of whatever is returned from this call into the cell.

Related

empty TableModel after instantiating

Newbie seeking help please :-)
I am working on a little project to get familiar with Java desktop development and Database connectivity.
Attached code gives me an empty TableModel after instantiating therefore no data displayed in the JFrame.
Test class is instantiated from the menue of the main window with Test.showFrame();.
package ...
import ...
public class Test extends JPanel {
public Test() {
initializePanel();
}
private void initializePanel() {
// Creates an instance of TableModel
CategoryTableModel tableModel = new CategoryTableModel();
System.out.println(tableModel.getRowCount());
// Creates an instance of JTable with a TableModel
// as the constructor parameters.
JTable table = new JTable(tableModel);
table.setFillsViewportHeight(true);
JScrollPane scrollPane = new JScrollPane(table);
this.setPreferredSize(new Dimension(500, 200));
this.setLayout(new BorderLayout());
this.add(scrollPane, BorderLayout.CENTER);
}
public static void showFrame() {
JPanel panel = new Test();
panel.setOpaque(true);
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
class CategoryTableModel extends AbstractTableModel {
private List<Category> all = null;
private Iterator<Category> iterator = null;
private int tableRowCount;
private TableModel tableModel;
public CategoryTableModel(){
Vector tableData = new Vector();
// TableModel's column names
Vector<String> tableHeaders = new Vector<String>();
tableHeaders.add("Category");
// Database call
all = new ReadCategory().allCategories();
// TableModel's data
for(Object o : all) {
Vector<Object> row = new Vector<Object>();
all.forEach((n) -> row.add(new Category().getName()));
tableData.add(row);
System.out.println("row added");
}
tableRowCount = tableData.size();
tableModel = new DefaultTableModel(tableData, tableHeaders);
System.out.println(tableModel.getRowCount());
}
#Override
public int getRowCount() {
return 0;
}
#Override
public int getColumnCount() {
return 0;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return null;
}
}
}
Database call is fetching data via Hibernate and stores data in a .
Thanks for help.
In its most basic form a table model for a JTable defines the columns, the mapping of object to column and holds the data for the JTable to call upon. If we take your current table model and cut it down to fit this basic requirement we get the following.
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
public class CategoryTableModel extends AbstractTableModel {
private final List<Category> tableData = new ArrayList<>();
public void add(Category cat) {
tableData.add(cat);
fireTableDataChanged();
}
#Override
public String getColumnName(int column) {
String result = "";
if (column == 0) {
result = "Category Name";
}
return result;
}
#Override
public int getRowCount() {
return tableData.size();
}
#Override
public int getColumnCount() {
return 1;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return tableData.get(rowIndex).getName();
}
return null;
}
}
Notice that we do not define any data in the model itself. All we define is some storage for the data and the column name of the single column that we require.
I have added an add() method that allows you to add data to the model (you may wish to define remove etc. yourself). When you add or remove data from the model you must always let the JTable know that the data has changed by calling fireTableDataChanged() so that the table can redraw itself.
To use this table model you will need to do
CategoryTableModel model = new CategoryTableModel();
model.add(new Category());
JTable table = new JTable(model);
You can replace the model.add() with a loop that iterates over your data and adds it to the model.

How do you load values into a JTable so that it shows the previous values when the form is opened?

How do you load array values into a JTable such that whenever the form is opened, it shows the previous values of the table? I do not want to connect the form to any databases.
This is my code so far, it allows me to enter texts to the text field, and when I click "create customer" button, it stores the value into the JTable. However if I exit and reopen the form, the data previously in the table disappears. And i have done some research, but it seems like connecting netbeans to a database is the only way to save and retrieve data. However, I believe that storing data into the array is possible too, but Ii do not know how to bring out the value in the array into the table.
I need some help. It is for my school project.
FYI, some of the notations I've used: rbtn = radiobutton, tb = textfields, lbl = label
public class Customer extends javax.swing.JFrame {
String gender;
int year = Calendar.getInstance().get(Calendar.YEAR);
int month = Calendar.getInstance().get(Calendar.MONTH);
int day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
int m=10; //array memory size
String[] name = new String[m];
String[] age = new String[m];
String[] genderm = new String [m];
String[] id = new String [m];
String[] mobile = new String [m];
String[] email = new String [m];
String[] address = new String [m];
String[] date = new String [m];
String[] photo = new String[m];
public Customer() {
initComponents();
tbdate.setText(day+"/"+(month+1)+"/"+year);
lblphoto.setIcon(null);
}
private void btncreateActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if (rbtnmale.isSelected()){
gender = "Male";
}
else if (rbtnfemale.isSelected()){
gender = "Female";
}
DefaultTableModel model = (DefaultTableModel) jtablecustinfo.getModel();
model.addRow(new Object[]{tbname.getText(),tbage.getText(),gender,tbid.getText(),tbmobile.getText(),tbemail.getText(),tbaddress.getText(),tbdate.getText(),lblphoto.getIcon()});
for(int i=0;i<m;i++){
name[i]=tbname.getText();
age[i] = tbage.getText();
genderm[i]=gender;
id[i]=tbid.getText();
mobile[i]=tbmobile.getText();
email[i]=tbemail.getText();
address[i]=tbaddress.getText();
date[i]=tbdate.getText();
photo[i]= tbimage.getText();;
}
//Reset everything after creation
JOptionPane.showMessageDialog(null,"Successfully Created Customer");
tbname.setText("");
tbage.setText("");
tbid.setText("");
tbmobile.setText("");
tbemail.setText("");
tbaddress.setText("");
tbdate.setText("");
rbtnmale.setSelected(false);
rbtnfemale.setSelected(false);
tbdate.setText(day+"/"+(month+1)+"/"+year);
gender = "";
tbimage.setText("");
lblphoto.setText(" -Import photo-");
lblphoto.setIcon(null);
}
I have included the main points of my code, hope it is sufficient to view!
For small amounts of data, consider java.util.prefs.Preferences.
Would you be able to provide me with some examples on how to use it?
Several examples are examined in the Preferences API Overview and the example cited here (API and code). Alternatively, consider javax.jnlp.PersistenceService, cited here, "for applications that are running in the restricted execution environment."
This minimal example updates a single cell by adding the previously saved value to the table and overriding the table model's setValueAt() implementation to save any change. Edit the table, quit and restart to see the effect.
package org.name.table;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.prefs.Preferences;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
/**
* #see https://stackoverflow.com/a/34616583/230513
*/
public class TablePreference {
private void display() {
JFrame f = new JFrame("TablePreference");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(new JTable(new PrefModel()) {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(128, 32);
}
}));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static class PrefModel extends DefaultTableModel {
private static final int DEFAULT = 42;
private static final String VALUE_NAME = "value";
private final Preferences p = Preferences.userNodeForPackage(TablePreference.class);
public PrefModel() {
addColumn("A");
addRow(new Object[]{p.getInt(VALUE_NAME, DEFAULT)});
}
#Override
public void setValueAt(Object aValue, int row, int col) {
super.setValueAt(aValue, row, col);
p.putInt(VALUE_NAME, (int) aValue);
}
#Override
public Class<?> getColumnClass(int col) {
return getValueAt(0, col).getClass();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new TablePreference()::display);
}
}

Getting a row of names from the first column of JTable

I have a JTable with the column names " Names " , " Quantity " and " Unit " .
I'm coding a program where you get the ingredients names.
So i need to get the whole row of one column and String it all up together,
because i need to store it in mySql and i have already set it all as String.
Any idea how i can do this ?
My code are as follows :
JTable Code:
DefaultTableModel model = (DefaultTableModel)table.getModel();
if(!txtQty.getText().trim().equals("")){
model.addRow(new Object[]{ingCB.getSelectedItem().toString(),txtQty.getText(),unitCB.getSelectedItem().toString()});
}else{
JOptionPane.showMessageDialog(null,"*Quantity field left blank");
}
Getting the values and for storing :
for(int i = 1; i<= i ; i++){
ingredients = table.getName();
}
This is for loop is wrong and it does not work because i have a constructor to take in Ingredients but because it is inside the loop, it cannot take it in.
Any suggestions please ? Thank you.
Constructor :
Food e2 = new Food(Name, Description, priceDbl, Image, Category, Ingredients, promotion );
e2.createFood();
I'm coding a program where you get the ingredients names. So i need to get the whole row of one column and String it all up together, because i need to store it in mySql and i have already set it all as String.
Want to do so, try this. Here I am getting result into ArrayList and String, as I am commented ArrayList you can avoid it.
public class TableValuePrint extends JFrame implements ActionListener{
private final JButton print;
private final JTable table;
private String str="";
public TableValuePrint() {
setSize(600, 300);
String[] columnNames = {"A", "B", "C"};
Object[][] data = {
{"Moni", "adsad", "Pass"},
{"Jhon", "ewrewr", "Fail"},
{"Max", "zxczxc", "Pass"}
};
table = new JTable(data, columnNames);
JScrollPane tableSP = new JScrollPane(table);
JPanel tablePanel = new JPanel();
tablePanel.add(tableSP);
tablePanel.setBackground(Color.red);
add(tablePanel);
setTitle("Result");
setSize(1000,700);
print=new JButton("Print");
JPanel jpi1 = new JPanel();
jpi1.add(print);
tablePanel.add(jpi1,BorderLayout.SOUTH);
print.addActionListener(this);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TableValuePrint ex = new TableValuePrint();
ex.setVisible(true);
}
});
}
#Override
public void actionPerformed(ActionEvent ae) {
if(ae.getSource()==print){
// ArrayList list = new ArrayList();
for(int i = 0;i<table.getModel().getRowCount();i++)
{
//list.add(table.getModel().getValueAt(i, 0)); //get the all row values at column index 1
str=str+table.getModel().getValueAt(i,0).toString();
}
//System.out.println("List="+list);
System.out.println("String="+str);
}
}
}
Output
String=MoniJhonMax

Adding items to an already existing jlist from another class

I have a jList (named JList1) created using the Desing mode from NetBeans IDE, and I want to add items to that list using a secondary class which parses a big xml list and gets the data from it. My problem is that I dont really understand how to do this, I already tried a lot of different codes, tried with a model too, but cant get it right. I am new to java (and programming too), and I dont understand if I do something like
String[] ar = {"one", "two", "three"};
JList Jlist1 = new JList(ar);
this created a new jList instead of using my already created one, no ?
created using the Desing mode from NetBeans IDE,
maybe not good idea to be prisonier of code generated by
add a new Item to DefaultListModel
and I want to add items to that list using a secondary class which
parses a big xml list and gets the data from it.
sounds like as you have an issue with Concurency in Swing, updates to the already visible Swing GUI must be done on EDT
use SwingWorker#publish() for long and hard job (which parses a big xml list and gets the data from it.)
for example, add a new Item to DefaultListModel
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Testing extends JFrame {
private static final long serialVersionUID = 1L;
private DefaultListModel listModel = new DefaultListModel();
private JList list = new JList(listModel);
private int currentSelectedRow = 0;
private int xX = 0;
public Testing() {
setLocation(400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
for (int x = 0; x < 9; x++) {
listModel.addElement("" + x);
xX++;
}
JScrollPane sp = new JScrollPane(list);
add(sp, BorderLayout.CENTER);
JButton btn1 = new JButton("Reset Model CastingModel");
add(btn1, BorderLayout.NORTH);
btn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
list.clearSelection();
DefaultListModel model = (DefaultListModel) list.getModel();
model.removeAllElements();
// note Swing GUI by default to freeze if is removed more that
// 999 elemets from the JList or its underlaying XxxListModel,
// to use repeatly Actions from SwingTimer on short period
for (int x = 0; x < 9; x++) {
model.addElement("" + (x + xX));
xX++;
}
list.setModel(model);
}
});
JButton btn2 = new JButton("Reset Model directly from Model");
add(btn2, BorderLayout.SOUTH);
btn2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
list.clearSelection();
listModel.removeAllElements();
for (int x = 0; x < 9; x++) {
listModel.addElement("" + (x + xX));
xX++;
}
}
});
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Testing().setVisible(true);
}
});
}
}
String[] ar = {"one", "two", "three"};
JList Jlist1 = new JList(ar);
The constructor you are using is as follows
/**
* Constructs a <code>JList</code> that displays the elements in
* the specified array. This constructor creates a read-only model
* for the given array, and then delegates to the constructor that
* takes a {#code ListModel}.
* <p>
* Attempts to pass a {#code null} value to this method results in
* undefined behavior and, most likely, exceptions. The created model
* references the given array directly. Attempts to modify the array
* after constructing the list results in undefined behavior.
*
* #param listData the array of Objects to be loaded into the data model,
* {#code non-null}
*/
public JList(final E[] listData)
{
this (
new AbstractListModel<E>() {
public int getSize() { return listData.length; }
public E getElementAt(int i) { return listData[i]; }
}
);
}
So you need to have your array which you are passing as an argument to the constructor final. Also do make use of generics.
final String[] ar = {"one", "two", "three"};
JList<String> Jlist1 = new JList<String>(ar);
Lastly since you are using new keyword it is bound to create new object. Just make your original list point to this new JList object created using your array. Mind you have to make it final and cannot be changed later.

TableModelListener and multiple column validation

This is the first time for me to post here, so sorry if I made some mistake.
I am working on a JTable which column data have to verify some parameters, for example:
Column 3 values > 30
Column 4 values > 10
Column 5 values > 4
Also the first 2 columns are filled "automatically", putting 0s in the rest of the columns.
If that data is correct, in the Column 5 I would show an image of a tick, otherwise, I would show an image of a warning.
For verifying this I use the following code
ImageIcon accept = new javax.swing.ImageIcon(getClass().getResource("/resources/accept.png"));
ImageIcon deny = new javax.swing.ImageIcon(getClass().getResource("/resources/exclamation.png"));
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
double d1 = Double.valueOf(jTable.getValueAt(row, 2).toString());
double d2 = Double.valueOf(jT.getValueAt(row, 3).toString());
double d3 = Double.valueOf(jT.getValueAt(row, 4).toString());
if(d1>MAX_A||d2>MAX_B||d3>MAX_C){
jTable.setValueAt(deny, row, 5);
}
else{
jTable.setValueAt(accept, row, 5);
}
}
The problem of this code is that returns a Stack Overflow, and I don't know how to handle this.
Is there any other way to implement some verifier on a table that implies multiple cells?
Thanks in advance.
The problem of this code is that
returns a Stack Overflow, and I don't
know how to handle this.
The problem is that your code sets a value in the model listener so another tableChanged event is generated. Your code should be something like:
if (e.getColumn() != 5)
// do your code
I don't see a problem using a TableModelListener to dynamically set the value of a column based on data in another column. Here is a simple example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableProcessing extends JPanel implements TableModelListener
{
public TableProcessing()
{
String[] columnNames = {"Item", "Quantity", "Price", "Cost"};
Object[][] data =
{
{"Bread", new Integer(1), new Double(1.11), new Double(1.11)},
{"Milk", new Integer(1), new Double(2.22), new Double(2.22)},
{"Tea", new Integer(1), new Double(3.33), new Double(3.33)},
{"Cofee", new Integer(1), new Double(4.44), new Double(4.44)}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
#Override
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
// The Cost is not editable
#Override
public boolean isCellEditable(int row, int column)
{
return (column == 3) ? false : true;
}
};
model.addTableModelListener( this );
JTable table = new JTable( model );
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
String[] items = { "Bread", "Milk", "Tea", "Coffee" };
JComboBox<String> editor = new JComboBox<String>( items );
DefaultCellEditor dce = new DefaultCellEditor( editor );
table.getColumnModel().getColumn(0).setCellEditor(dce);
}
/*
* The cost is recalculated whenever the quantity or price is changed
*/
public void tableChanged(TableModelEvent e)
{
if (e.getType() == TableModelEvent.UPDATE)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 1 || column == 2)
{
TableModel model = (TableModel)e.getSource();
int quantity = ((Integer)model.getValueAt(row, 1)).intValue();
double price = ((Double)model.getValueAt(row, 2)).doubleValue();
Double value = new Double(quantity * price);
model.setValueAt(value, row, 3);
}
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Table Model Listener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TableProcessing());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
You probably get your error because of getFirstRow call. I think it's a bad idea to validate table structure in JTable.tableChanged - how do you know that the table was fully filled and ready for validation? I would suggest filling the whole table first, then invokation of validation. Maybe there would be also a good idea to use separate table to display validation results

Categories