I'm doing a chess game and I need to make a log table that prints every move. The LogTable class is like this:
public class LogTable {
private DefaultTableModel model;
private JTable table;
public LogTable(JPanel panel){
String[] columnNames = {"Move No.",
"White",
"Black"};
model = new DefaultTableModel(columnNames, 0);
table = new JTable();
//model.isCellEditable(i, i1)
table.setModel(model);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
panel.add(scrollPane);
}
public void newMove(chessPiece piece){
if (piece.getColor() == 0){
Object[] newRow = new Object[3];
newRow[0] = model.getRowCount()+1;
newRow[1] = piece.sayPos();
newRow[2] = " ";
model.addRow(newRow);
}
else {
model.setValueAt(piece.sayPos(), model.getRowCount(), model.getColumnCount());
}
}
}
But in the first black move it thows an ArrayOutOfBoundsException. The newMove function is called at the chessPiece class:
public void move(int newX, int newY, JPanelSquare jPanelSquareGrid[][], LogTable logTable){
resetShowValidMoves(jPanelSquareGrid);
logTable.newMove(this);
}
The rest of the move code is in each piece, which call super. I'm using the DefaultTableModel.
From Java API :
public DefaultTableModel(Object[] columnNames,int rowCount)
Constructs a DefaultTableModel with as many columns as there are elements in
columnNames and rowCount of null object values. Each column's name
will be taken from the columnNames array.
You instantiate the DefaultTableModel with 0 rows. So you can't set the value of an item in row 0 since it doesn't exist.
Related
I can't manage to display the JTable in a JFrame. Actually I have extracted the data from an ArrayList and filled the JTable row by row. I have checked that the JTable is filled, the number of rows is equal to the rows in the original ArrayList. Yet running the function shows a blank GUI. I really do not see the problem in my code:
public Graphicalinterface4() {
//super (new GridLayout(1,0));
//panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
getdata2 in=new getdata2();
try {
ArrayList<Piece> test=in.getList();
ArrayList<Piece> classified=in.classify(test);
JTable table=getlocaltable(classified);
table.setFillsViewportHeight(true);
JScrollPane scrPane=new JScrollPane(table);
//scrPane.setSize(800,690);
//scrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.add(scrPane);
//scrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
catch (IOException ex) {
ex.printStackTrace();
}
}
public JTable getlocaltable(ArrayList<Piece> in) {
//new Object[]{"Type","Company","reference","description","price","To order"}));
//DefaultListModel<Piece> testlst=new DefaultListModel<Piece>();
int sz=in.size();
String[] columns=new String[] {
"Type","Company","reference","description","price","To order"
};
DefaultTableModel model = new DefaultTableModel();
//JTable table=new JTable(null, in.toArray());
for (int i=0;i<sz;i++) {
Piece p=in.get(i);
String type=p.gettype();
String company=p.getasc();
String reference=p.getref();
String description=p.getdesc();
String price=p.getprice();
String image=p.getimage();
System.out.println(type);
//DefaultTableModel model=(DefaultTableModel) table.getModel();
model.addRow(new Object[]{type,company,reference,description,price,Integer.toString(0)});
}
JTable table=new JTable(model);
System.out.println(table.getRowCount());
return table;
}
static Graphicalinterface4 ssp;
public static void main(String[] args) throws IOException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {ssp=new Graphicalinterface4();}
});
}
DefaultTableModel model = new DefaultTableModel();
You have 0 columns in the TableModel. The columns displayed is determined by the columns in the TableModel, not the number of items in each row. So adding rows of data has no effect.
Read the DefaultTableModel API for the proper constructor to use that will accept the "columns" variable as a parameter.
Thanks! I had not initialized the DefaultTableModel correctly. In the API the String[] and Object[][]{} are inverted(DefaultTableModel(String, Object[][]{}), but this works for me.
public JTable getlocaltable(ArrayList<Piece> in) {
//new Object[]{"Type","Company","reference","description","price","To order"}));
int sz=in.size();
String[] columns=new String[] {
"Type","Company","reference","description","price","To order"
};
DefaultTableModel model = new DefaultTableModel(new Object[][]{}, columns);
//JTable table=new JTable(model);
for (int i=0;i<sz;i++) {
Piece p=in.get(i);
String type=p.gettype();
String company=p.getasc();
String reference=p.getref();
String description=p.getdesc();
String price=p.getprice();
String image=p.getimage();
System.out.println(type);
//DefaultTableModel model=(DefaultTableModel) table.getModel();
model.addRow(new Object[]{type,company,reference,description,price,Integer.toString(0)});
}
JTable table=new JTable(model);
System.out.println(table.getRowCount());
return table;
}
I'm unsure about how to assign values to a JTable without directly assigning values to the initial 2D Array, i.e. String data[][]= new String[5][5]{"abc","def","ghi","jkl","mno"};
If I declared my array of 2D String, followed by defaultTableModel, is there any way I can assign the values of abc, def, ghi, jkl, mno to the Array/JTable without doing it as above in a separate method maybe?
Update
JPanel invoiceViewPanel= new JPanel(null);
String data[][]= new String[4][10];
String columnHeaders[]={"Invoice ID","Invoice Name","Customer", "Complete?"};
DefaultTableModel model = new DefaultTableModel(data, columnHeaders) {
boolean[] Editable= new boolean[]{
false, false, false, true
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return editableCells[columnIndex];
}
#Override
public Class<?> getColumnClass(int columnIndex)
{
return columnClass[columnIndex];
}
};
JTable table=new JTable(model);
JScrollPane tableContainer=new JScrollPane(table);
final Class[] columnClass = new Class[]
{
Integer.class, String.class, String.class, Boolean.class
};
public void launch()
{
this.setLayout(new FlowLayout());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(invoiceViewPanel);
invoiceViewPanel.add(tableContainer);
this.add(tableContainer);
this.setTitle("Invoices");
this.setSize(500,600);
this.setVisible(true);
this.setResizable(false);
}
This is a basic version of my code. It is just the initialising of my JTable.
I have a text file of the format
001/ TV Purchase/ John Smith/ true
002/ Refrigerator Purchase/ Jean Smith/ false
All Swing components work with a Model. To update the component you update the model.
So in the case of a JTable you can create an "empty" model for your table by using:
String[] columnNames = { "Column1", "Column2", ... };
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
JTable table = new JTable( model );
Now when you want to add data to the model you can use:
Object[] row = {"data1", data2", ... };
model.addRow( row );
Read the DefaultTableModel API for more methods to change the data. You can also add a Vector of data to the model.
I'm trying to implement a checkbox interface which allows a user to show/hide columns in a JTable, but when I remove the column, the column seems to move position and there is no way of knowing 100% where the columns are. The table is built with this code:
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
String[] columnNames = {"Artist","Track","Album","Genre","Year","Filetype"};
for (String column : columnNames) {
model.addColumn(column);
}
table.createDefaultColumnsFromModel();
table.getTableHeader().setReorderingAllowed(false);
Here's the code I have for implementing the checkbox listeners:
if (e.getSource() == artist) {
if (!artist.isSelected()) {
table.removeColumn(table.getColumnModel().getColumn(0));
} else {
table.addColumn(table.getColumnModel().getColumn(0));
}
}
if (e.getSource() == trackName) {
if (!trackName.isSelected()) {
table.removeColumn(table.getColumnModel().getColumn(1));
} else {
table.addColumn(table.getColumnModel().getColumn(1));
}
}
/* etc */
You can to use the Table Column Manager.
It will manager the hiding/showing of the table columns for you.
I have a jtable functioning normally. The table lists tasks, and each task you an associated status.
I want every status is associated with an image.
So the image would appear in the table as show below.
------Code for jTable----------
DefaultTableModel tmSubTask = new DefaultTableModel(null, new String[]{"Status", "Priority", "Task", "SubTask", "Desc", "Prevision Begin", "Time", "Prevision Duration", "Prevision hour", "Begin", "Hour Begin","End Date" ,"End Hour", "Duration"});
List<SubTask> subTask;
ListSelectionModel lsmSubTask;
Connection conexao = null;
PreparedStatement pst= null;
ResultSet rs = null;
private void showSubTask(List<SubTask> subTask) {
while (tmSubTask.getRowCount() > 0) {
tmSubTask.removeRow(0);
}
if (subTask.size() == 0) {
JOptionPane.showMessageDialog(null, "showSubTask");
} else {
String[] line = new String[]{null, null, null};
for (int i = 0; i < SubTask.size(); i++) {
tmSubTask.addRow(linha);
tmSubTask.setValueAt(subTask.get(i).getStatus(), i, 0);
tmSubTask.setValueAt(subTask.get(i).getIdPriority(), i, 1);
tmSubTask.setValueAt(subTask.get(i).getIdTask(), i, 2);
tmSubTask.setValueAt(subTask.get(i).getIdSubTask(), i, 3);
tmSubTask.setValueAt(subTask.get(i).getDescSubTask(), i, 4);
tmSubTask.setValueAt(subTask.get(i).getDateBegin(), i, 5);
tmSubTask.setValueAt(subTask.get(i).getTerm(), i, 6);
tmSubTask.setValueAt(subTask.get(i).getDuration(), i, 7);
tmSubTask.setValueAt(subTask.get(i).gethourBeginP(), i, 8);
tmSubTask.setValueAt(subTask.get(i).getDateBegin(), i, 9);
tmSubTask.setValueAt(subTask.get(i).getHourBegin(), i, 10);
tmSubTask.setValueAt(subTask.get(i).getDateEnd(), i, 11);
tmSubTask.setValueAt(subTask.get(i).getHourEnd(), i, 12);
tmSubTask.setValueAt(subTask.get(i).getDuration(), i, 13);
}
}
}
---------------jTable--------------
---------------What I want---------
Imagine if Status like Delay in jTable show image red.
I honestly don't even know where to start.
I apologize if I did not make myself clear.
Thank all any help you can give me.
Greetings.
Any questions I will try to explain as best as possible.
Add an ImageIcon to the table and override the getColumnClass(...) method of the JTable to return Icon.class and the table will use an appropriate renderer to display the Icon. Something like:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableIcon extends JFrame
{
public TableIcon()
{
Icon aboutIcon = new ImageIcon("about16.gif");
Icon addIcon = new ImageIcon("add16.gif");
Icon copyIcon = new ImageIcon("copy16.gif");
String[] columnNames = {"Picture", "Description"};
Object[][] data =
{
{aboutIcon, "About"},
{addIcon, "Add"},
{copyIcon, "Copy"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable( model )
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
new TableRowResizer(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnAdjuster tca = new TableColumnAdjuster(table);
tca.adjustColumns();
}
public static void main(String[] args)
{
TableIcon frame = new TableIcon();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
}
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