I am currently using a JTable to display a few patient details. I have a JCheckBox, that when ticked adds a new column to the table and adds the data to the new column. When it is unticked, it should remove the column, sort of like adding extra filters to the table. However, when I tick the box again after unticking it, it duplicates the columns in the table.
I tried to use the fireTableStructureChanged() method, but it would never update the table and so the columns stay there even if the checkbox was unticked. But if I remove it, then when I untick the the checkbox it works, but then the duplication problem comes back. I pasted my actionPerformed() method for when the checkbox is ticked. The first image is of my table before I click my Checkbox. The second is when I click the Checkbox and the column is added. Lastly the third is when I untick the checkbox and tick again. Any help will be much appreciated.
#Override
public void actionPerformed(ActionEvent e)
{
if (gui.getChkCholesterol().isSelected() == true)
{
try {
gui.getRightTableModel().addColumn("Cholesterol");
newColumnIndeces.put("2093-3",gui.getRightTable().getColumnCount()-1);
gui.getRightTableModel().addColumn("Cholesterol Effective Date/Time");
newColumnIndeces.put("2093-3e",gui.getRightTable().getColumnCount()-1);
if(gui.getRightTable().getRowCount()>0)
{
int columnNumberValue = newColumnIndeces.get("2093-3");
int columnNumberDate = newColumnIndeces.get("2093-3e");
for (int i = 0; i<gui.getRightTable().getRowCount(); i++)
{
String value = op.getPatientObservationValue(gui.getRightTable().getValueAt(i,0).toString(),"2093-3");
String date = op.getPatientObservationEffectiveDate(gui.getRightTable().getValueAt(i,0).toString(),"2093-3");
gui.getRightTableModel().setValueAt(value, i, columnNumberValue);
gui.getRightTableModel().setValueAt(date, i, columnNumberDate);
}
}
} catch (ParseException parseException) {
parseException.printStackTrace();
}
setCellColourForTable();
timer.schedule(new RefreshTable(), 0, seconds);
}
else
{
gui.getRightTable().removeColumn(gui.getRightTable().getColumnModel().getColumn(newColumnIndeces.get("2093-3")));
gui.getRightTable().removeColumn(gui.getRightTable().getColumnModel().getColumn(newColumnIndeces.get("2093-3e")-1));
newColumnIndeces.remove("2093-3");
newColumnIndeces.remove("2093-3e");
timer.cancel();
timer = new Timer();
}
gui.getRightTableModel().fireTableStructureChanged();
}
You add a column to the model by using:
gui.getRightTableModel().addColumn("Cholesterol");
This will notify the view that the data has changed and the table will also be updated.
However, you remove the column from the table using:
gui.getRightTable().removeColumn(…);
This only removes the column from the "table view". The column has not been removed from the DefaultTableModel. So the next time you add a column it just gets added to the end of the DefaultTableModel.
So the solution is to remove the column from the DefaultTableModel, not the table.
Unfortunately there is no removeColumn(…) method.
However because your requirement is to only add/remove columns from the end of the DefaultTableModel you can use:
model.setColumnCount(model.getColumnCount() - 2);
which will effectively remove the last two columns from the model.
The other option is to not keep adding columns to the DefaultTableModel, but instead you can just add/remove TableColumns from the TableColumnModel directly. So this would mean the data for the Cholestoral column would always be in the model, but the view would just not display the columns.
So instead of using the model.addColumn(…) you would use the table.addColumn(…) method.
Related
I have a jtable, in which I keep certain information, and I have a 'clear' button that cleans all the information in the table.
The problem is, when I double click on a cell in the table and then I press the clear button, the table is emptied correctly but the selected cell continues appearing in the table as if it had not been deleted. As you can see in the next screenshot.
This is the java code i use to clear the information of the jtable:
public void resetArea(JTable tabla) {
DefaultTableModel dm = (DefaultTableModel)tabla.getModel();
while(dm.getRowCount() > 0) {
dm.removeRow(0);
}
}
That is caused as the cell editor is still shown. First do:
tabla.removeEditor();
Try this
DefaultTableModel dm = (DefaultTableModel)tabla.getModel();
while(dm.getRowCount() > 0) {
dm.removeRow(dm.getRowCount()-1);
}
Things that i am trying to achieve:
Select the row and add in values, the first value at col=0 will determine what will generate at col=2 and what col=2 value is will generate values for col=3.
To achieve what i have said on the selected row, for example if i have more than 2 rows of data which is empty. When i fill in the first row of data, the second row of data should be remain untouched. The second row of values are only generated when i click of the second row value.
Lastly this is just another button that i have which is a "save" button where it will retrieve the data from the table and store it. However i am getting this problem where when my mouse is still selected on the cell, that selected cell value is not being passed in and stored. So is there a way when i click the button, i can deselect the cell?. Side note i have used clearSelection and it does not work.
Currently what i have:
At the moment i managed to do the change where when i click a value from the col=0 and it will update the value for col=1. However i am now stuck at how i am going to get the value from the col=1 to generate my values for col=3 which is the last col. I have tried adding another if else in the method however that does not work.
At the moment the values i add in are combobox these combobox values are derived from a method that passes in the selection choice of the values from their respective cols.
Method for table listener:
public static void TableListen(JTable Model,SQLObject so){
Model.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent evt) {
if(Model.getModel().getRowCount()!=0){
if(Model.getSelectedColumn()==0){
if(!Model.getModel().getValueAt( Model.getSelectedRow(), 0).toString().equals("-Selection-")){
String treatmentChoice=Model.getModel().getValueAt(Model.getSelectedRow(), Model.getSelectedColumn()).toString();
JComboBox<String> comboBox = null;
TableColumn feedingCol=Model.getColumnModel().getColumn(1);
comboBox=DosageObject.GetListOfMedication(so,treatmentChoice);
feedingCol.setCellEditor(new DefaultCellEditor(comboBox));
}
}
}
}
});
}
I have a JTable with several columns. I override the getColumnClass method of the table model in order to specify which columns hold Integer values. So basically when a user tries to enter a String into an Integer column, he/she is not allowed to do so. The problem is that the user can still click on a button on my form which then uses the improper value in that cell.
How can I not allow the user to click on any buttons as long as one of the cells in the table is still being edited?
Add a PropertyChangeListener to the JTable:
#Override
public void propertyChange(PropertyChangeEvent e)
{
// A cell has started/stopped editing
if ("tableCellEditor".equals(e.getPropertyName()))
{
if (table.isEditing())
// disable buttons;
else
// enable buttons;
}
}
Or, if you don't want to disable the buttons, you can just add code to the ActionListener to check if the table.isEditing() and if so then just return.
You could use one of the 3 methods returning information on the editing process to enable your button.
JTable table = new JTable();
table.getEditingColumn();
table.getEditingRow();
table.getEditorComponent();
Check JTable documentation to see which could be best used for your case. You could make your button enabled only if
table.getEditorComponent();
returns null for example.
add a TableModelListener to your JTable
you should override its tableChanged method somewhat like this :
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel)e.getSource();
String columnName = model.getColumnName(column);
Object data = model.getValueAt(row, column);
//Check the data!!!
//Check the data!!!
//Check the data!!!
//disable the button if needed right here
}
ref:http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#modelchange
I have a JTable and any single row in it has associated a different tooltip when mouse hover a row. I have created a "filter" for this table; when it is applied it perfectly hides the rows need to be hidden but when I hover the mouse on the filtered rows, looks like the tooltip is referring to the row that occupied the same row position of the new current row.
For example:
Table
ROW 1 -> tooltip 1
ROW 2 -> tooltip 2
Apply Filter to Table:
ROW 2 -> tooltip 1
So ROW 2 is displaying the tooltip 1 instead of 2.
TableRowSorter<TableModel> sorter = (TableRowSorter<TableModel>) table.getRowSorter();
sorter.setRowFilter(RowFilter.regexFilter(text));
My table that extends JTable has:
#Override
public String getToolTipText(MouseEvent e) {
final int rowIndex = rowAtPoint(e.getPoint());
TableModel model = getModel();
// take the value from the first column of the selected row
String tip = (String) getModel().getValueAt(rowIndex, 0));
return tip;
}
So it looks like using the model is not (quite obvious) updated respect to the filter. I tried using TableModel model = getRowSorter().getModel() too but without any luck.
How can I point to a correct "filtered model" to retrieve the correct row position?
UPDATE:
I have replaced the "rowIndex" code like this:
final int rowIndex = convertRowIndexToModel(rowAtPoint(e.getPoint()));
It partially solves the problem, but when some rows are added dynamically to the table with the filter applied and I hover new rows I get the exception (with relative API description):
IndexOutOfBoundsException -> if sorting is enabled and passed an index outside the range of the JTable as determined by the method getRowCount
You need to convert the views row index to the model's row index
Have a look at JTable#convertRowIndexToModel
You should not override that JTable#getToolTipText method. Just set the tooltip-text on the component returned by your renderer. The JTable will pick it up automatically. You can see this in the implementation of the getTooltipText method of the JTable
I am trying to display the data of hidden column as tooltip. Hiding is working perfectly using the following code:
JTable table = new JTable(model){
//Implement table cell tool tips.
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
int colIndex = columnAtPoint(p);
int realColumnIndex = convertColumnIndexToModel(colIndex);
try {
tip = getValueAt(rowIndex, 8).toString();
} catch (RuntimeException e1) {
//catch null pointer exception if mouse is over an empty line
}
return tip;
}
};
TableColumnModel tcm = table.getColumnModel();
TableColumn tc;
for(int i = 1; i <= 7; i++){
tc = tcm.getColumn(8);
tcm.removeColumn(tc);
}
But the tooltip is not showing the data of hidden column (getValue function is not returning value). So do hiding the column delete the data as well ?
You do not need to for loop as you do not use the i variable ;-)
The removeColumn on the JTable does not remove the data from the model, as clearly stated in the javadoc
Removes aColumn from this JTable's array of columns. Note: this method does not remove the column of data from the model; it just removes the TableColumn that was responsible for displaying it.
There is no mention in the javadoc for the same method on the TableColumnModel, but I would assume it works the same way, but you can always give it a try to call it on the JTable instead
The real problem in your code is the use of getValueAt, which uses the row and column index of the table, and not of the model
Note: The column is specified in the table view's display order, and not in the TableModel's column order. This is an important distinction because as the user rearranges the columns in the table, the column at a given index in the view will change. Meanwhile the user's actions never affect the model's column ordering.
And since you removed that column, it simply does not exists for the table. Call the getValue method on the model instead, and do not forget to convert the row index