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);
}
}
Related
I have made a JOptionPane which contains a JPanel. The panel contains one button and one Jtable.
JPanel p = atomicAttack.getPanel(); //make the panel and return it
JOptionPane.showOptionDialog(null, p,"Atomic Attacks",
JOptionPane.DEFAULT_OPTION,JOptionPane.INFORMATION_MESSAGE,
null, new Object[]{}, null);
and inside the JButton i have:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
selectedId=jTable1.getValueAt(jTable1.getSelectedRow(), 0).toString();
}
I need to when the user clicks on the button, the JOption get closed and the selectedId get return from the JOptionPane?
I have seen this, but it is not exactly what i am looking for.
Because the button does not return the value for me.
Focus on the models and things will be easier.
public static void main(String[] args) {
DefaultTableModel tableModel = new DefaultTableModel();
tableModel.addColumn("Selection", new Object[] { "A", "B", "C" });
JTable table = new JTable(tableModel);
ListSelectionModel selectionModel = table.getSelectionModel();
JPanel p = new JPanel(new BorderLayout());
p.add(table, BorderLayout.CENTER);
int option = JOptionPane.showConfirmDialog(null, p, "Atomic Attacks", JOptionPane.OK_CANCEL_OPTION,
JOptionPane.INFORMATION_MESSAGE);
if (JOptionPane.OK_OPTION == option) {
printSelection(selectionModel, tableModel);
} else {
selectionModel.clearSelection();
}
}
private static void printSelection(ListSelectionModel selectionModel, TableModel tableModel) {
for (int i = selectionModel.getMinSelectionIndex(); i <= selectionModel.getMaxSelectionIndex(); i++) {
if (selectionModel.isSelectedIndex(i)) {
Object selectedValue = tableModel.getValueAt(i, 0);
System.out.println(selectedValue);
}
}
}
If you now select multiple rows
and press the ok button the result will be
A
C
If you want a single selection you can just set
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
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.
basically what i am trying to do is, i have a JList which contain a list of available drive, if one of that drive selected by user then i will show all html files which located in selected drive in a JTable, so i put an event listener for my JList and then i create a JTable and put all data there and show it in the container. the code look like this:
static class HtmlListing implements ListSelectionListener
{
public void valueChanged(ListSelectionEvent event)
{
if (!event.getValueIsAdjusting())
{ //trying to remove and re-add controls in container.
EastCont.removeAll();
globarr = new ArrayList<File>(); // global variable
FileListing fl = new FileListing();
fl.walk(fileList1.getSelectedValue() + "work\\airasia\\html", 500, 0);
//if(globarr.size() > 0)
//{
Object[][] data = new Object[globarr.size()][globarr.size()];
for(int i = 0; i < globarr.size(); i++)
{
if(globarr.get(i).isFile())
{
String filename = globarr.get(i).getName().toString();
String date = sdf.format(globarr.get(i).lastModified());
Object[] obj = new Object[] {filename, filename.substring(filename.lastIndexOf(".") + 1), date, globarr.get(i).getAbsolutePath()};
data[i] = obj;
}
}
Object[] column = new Object[]{"name ", "type", "date modified", "path"};
DefaultTableModel model = new DefaultTableModel(data, column);
model.fireTableDataChanged();
table = new JTable(model)
{
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int row, int column)
{
return false;
};
};
table.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
int rowIdx = table.getSelectedRow(); // path to your new file
TableModel tm = table.getModel();
String path = tm.getValueAt(rowIdx, 3).toString();
File htmlFile = new File(path);
try // open the default web browser for the HTML page
{
Desktop.getDesktop().browse(htmlFile.toURI());
//Desktop.getDesktop().open(htmlFile);
}
catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
table.removeColumn(table.getColumnModel().getColumn(3)); //hide column path from display
table.setFillsViewportHeight(true);
table.setIntercellSpacing(new Dimension(0, 5));
table.setShowGrid(false);
scrollPane = new JScrollPane(table);
EastCont = new JPanel();
EastCont.setLayout(new BorderLayout());
EastCont.add(scrollPane);
EastCont.setPreferredSize(new Dimension(1050, 1000));
//EastCont.repaint();
//EastCont.revalidate();
gui.add(EastCont, BorderLayout.EAST);
gui.revalidate();
gui.repaint();
// }
// else
// {
// EastCont.remove(table);
// gui.remove(EastCont);
// gui.revalidate();
// gui.repaint();
// }
}
this code work only for first time, but does not working for second time and so on, so what i miss here? any help would be great. thank you.
DefaultTableModel model = new DefaultTableModel(data, column);
//model.fireTableDataChanged();
//table = new JTable(model)
table.setModel( model );
Don't create a new table change reset the model of your current table. The rest of the code in that method is not necessary either since you are not creating any new GUI components.
Also, never invoke a fireXXX method. That is the responsibility of the TableModel.
I have this JTable having a DefaultTableModel as its model.
On the table I have several swing component, JComboBox and JCheckBox, set on a particular column via DefaultCellEditor and DefaultCellRenderer.
The TableModelListener was added to the table to capture changes on editable columns.
The rest of the columns will display details of the selected component, i.e. item code -> item price, item count, item classification,etc.
I have this problem wherein if the selectedItem of the JComboBox(itemCode) changes, the items of the other JComboBox(itemClassification) changes. But together with the change of the other JComboBox I need to display the item price on the same table. This change refires the valueChanged method which makes an infinite loop of valueChanged.
How can I get rid of the infinite loop thing?
One way is to check the update event to see what column the event is for and ignore columns that are automatically updated:
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 could remove the listener when making changes from within the listener itself, and then re-add it when done with changes. Or you could give the Listener a boolean property that activates and deactivates the listener code, and set it appropriately from within the listener.
Actually...
I have also my answer.
I just get into the API of TableModelListener and I found the TableModelEvent.getColumn()
Thanks guys...
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