I want to store the GWT FlexTable row number that contains a date when that date is changed. The code is:
//Add change handler for the task completion date.
dateCompletion.addValueChangeHandler(new ValueChangeHandler<java.util.Date>() {
public void onValueChange(ValueChangeEvent<java.util.Date> event) {
//TODO currentRow = flexAwardDescription.getRowIndex();
//Display all YM who have not completed this task.
AsyncCallback<List<YouthMember>> callback = new YMWithoutAwardHandler<List<YouthMember>>(CubBulkAward3View.this);
rpc.getYMWithoutAwardList(ymAwardDetails.getad_Id(), callback);
}
});
I have found an answer for click event; however, not for change event.
Please check my answer here: Gwt getCellForEvent flexTable
There's no obvious way to do it, what you can do is
Get event source
Cast it to widget
Get it's Element via .getElement() then use getParent() to get Cell, and getParent() one more time to get row element.
You can get it's index then, comparing it to rows from rowFormatter in a loop.
The work around I came up with is to capture row number on the click event (as you must first click before you can change) and then use this row number if a change event occurs.
//Get the row number of the row selected to display the names below it.
flexAwardDescription.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
currentRow = flexAwardDescription.getCellForEvent(event).getRowIndex();
}
});
//Add change handler for the task completion date.
dateCompletion.addValueChangeHandler(new ValueChangeHandler<java.util.Date>() {
public void onValueChange(ValueChangeEvent<java.util.Date> event) {
//Check if this is the completion row
if (ymAwardDetails.getad_Description().matches("(.*)Completed:(.*)")) {
groupCompleted = "C";
}else{
groupCompleted = "S";
}
awardDescriptionID = ymAwardDetails.getad_Id();
//Display all YM who have not completed this task.
AsyncCallback<List<YouthMember>> callback = new YMWithoutAwardHandler<List<YouthMember>>(CubBulkAward3View.this);
rpc.getYMWithoutAwardList(ymAwardDetails.getad_Id(), accountId, callback);
}
});
I am using GXt GWt and am trying to get the values from a selected row in a tree grid, but can't seem to get it working..
E.g. if the user clicks row, i want to be able to get the values for all the columns in that row.
cm = new ColumnModel(createColumnConfig());
// Create grids based on data (held in stores), and attach listeners for when a row is clicked
final TreeGrid<Build> nightlyResultsGrid = createTreeGrid(nightlyResultsStore);
nightlyResultsGrid.addListener(Events.RowClick, new Listener<BaseEvent>()
{
public void handleEvent(BaseEvent clickEvent)
{
GridEvent gridEvent = (GridEvent)clickEvent;
gridEvent.getModel().get("Platform").toString();
gridEvent.getModel().get("Date").toString();
gridEvent.getModel().get("Build").toString();
}
}
The code above keeps generating an exception..
15:58:09.861 [ERROR] [dashboard] Uncaught exception escaped
java.lang.NullPointerException: null
at com.rory.mep.ui.metrics.client.UserInterface$3.handleEvent(UserInterface.java:109)
at com.extjs.gxt.ui.client.event.BaseObservable.callListener(BaseObservable.java:178)
at com.extjs.gxt.ui.client.event.BaseObservable.fireEvent(BaseObservable.java:86)
at com.extjs.gxt.ui.client.widget.Component.fireEvent(Component.java:456)
at com.extjs.gxt.ui.client.widget.grid.Grid.onClick(Grid.java:811)
at com.extjs.gxt.ui.client.widget.treegrid.TreeGrid.onClick(TreeGrid.java:745)
Any help is much appreciated.
Be sure to read the Javadocs for events when you use them. From Grid's docs:
RowClick : GridEvent(grid, rowIndex, cellIndex, event)
Fires after a row is clicked.
grid : this
rowIndex : the row index
cellIndex : cell index
index : the cell index
event : the dom event
The model isn't available, so getModel() is returning null. Instead, use the rowIndex with the store to get the model.
I'm trying to have a JTable edition working like in excel: if I start editing a cell, the cell becomes empty for receiving the new entry. The goal is to avoid the user having to delete the existing cell content first.
I can already detect cell start/stop edition by adding a PropertyChangeListener working as follow:
public void propertyChange(PropertyChangeEvent e)
{
// A cell has started/stopped editing
if ("tableCellEditor".equals(e.getPropertyName()))
{
if (table.isEditing())
processEditingStarted();
else
processEditingStopped();
}
}
Trying to clear the table model at processEditingStarted() does not work with the code bellow:
private void processEditingStarted()
{
SwingUtilities.invokeLater( this );
}
public void run()
{
row = table.convertRowIndexToModel( table.getEditingRow() );
column = table.convertColumnIndexToModel( table.getEditingColumn() );
oldValue = table.getModel().getValueAt(row, column);
newValue = null;
table.getModel().setValueAt(null, row, column);
table.updateUI();
}
However the editor content keeps the former value.
Does someone has clues to hide the current value of the cell during edition?
Optionnaly it should be able to restore the former cell content if the user did not actually modify the value.
I"ve never seen a spreadsheet remove data when you start editing a cell.
Table Select All Editor shows a different approach.
I did it like this. First I am using the event keyReleased and then getting the row and column number on which I am working and then setting the value at that row. Code goes like this.
private void purchases_TBLKeyReleased(java.awt.event.KeyEvent evt) {
int rowWorking = purchases_TBL.getSelectedRow();
int columnWorking = purchases_TBL.getSelectedColumn();
if(columnWorking==3){
model.setValueAt(null, rowWorking, columnWorking);
}
}
This makes the third column of the table null as soon as I focus move on to that using keyboard.
Note: The same piece of code can be placed in MouseClicked event.
The default behaviour in a JTable seems to be that if I reach the last row of a column and hit return, I am taken to the first row of the next column. Is there a way to avoid this? Please suggest a way that I could stay at the last row of the same column. I also want to avoid a situation where I am taken to the next column and then detect that and go back to the previous one, because I have some listeners associated with it.
Any help is appreciated.
to change any of the navigational behaviour, replace the default navigational actions with your own. Best by wrapping the defaults: conditionally either do the default or your custom stuff. Something like
Object key = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.get(KeyStroke.getKeyStroke("ENTER"));
final Action action = table.getActionMap().get(key);
Action custom = new AbstractAction("wrap") {
#Override
public void actionPerformed(ActionEvent e) {
int row = table.getSelectionModel().getLeadSelectionIndex();
if (row == table.getRowCount() - 1) {
// do custom stuff
// return if default shouldn't happen or call default after
return;
}
action.actionPerformed(e);
}
};
table.getActionMap().put(key, custom);
We're seeing JTable selection get cleared when we do a fireTableDataChanged() or fireTableRowsUpdated() from the TableModel.
Is this expected, or are we doing something wrong? I didn't see any property on the JTable (or other related classes) about clearing/preserving selection on model updates.
If this is default behavior, is there a good way to prevent this? Maybe some way to "lock" the selection before the update and unlock after?
The developer has been experimenting with saving the selection before the update and re-applying it. It's a little slow.
This is Java 1.4.2 on Windows XP, if that matters. We're limited to that version based on some vendor code we use.
You need to preserve the selection and then re-apply it.
First of all you will need to get a list of all the selected cells.
Then when you re-load the JTable with the new data you need to programmatically re-apply those same selections.
The other point I want to make is, if the number or rows or columns in your table are increasing or decreasing after each table model reload, then please don't bother preserving the selection.
The user could have selected row 2 column 1 having a value say "Duck", before model updation. But after model updation that same data can now occur in row 4 column 1, and your original cell row 2 column 1 could have new data such as "Pig". Now if you forcibly set the selection to what it was before the model updation, this may not be what the user wanted.
So programmatically selecting cells could be a double edged sword. Don't do it, if you are not sure.
You can automatically preserve a table's selection if the STRUCTURE of that table hasn't changed (i.e. if you haven't add/removed any columns/rows) as follows.
If you've written your own implementation of TableModel, you can simply override the fireTableDataChanged() method:
#Override
public void fireTableDataChanged() {
fireTableChanged(new TableModelEvent(this, //tableModel
0, //firstRow
getRowCount() - 1, //lastRow
TableModelEvent.ALL_COLUMNS, //column
TableModelEvent.UPDATE)); //changeType
}
and this should ensure that your selection is maintained provided that only the data and not the structure of the table has changed. The only difference between this, and what would be called if this method weren't overridden is that getRowCount() - 1 is passed for the lastRow argument instead of Integer.MAX_VALUE, the latter of which acts a signifier that not only has all the data in the table changed but that the number of rows may have as well.
I had the same issue in an application. In my case the model in the table was a list of objects, where the object properties where mapped to columns. In that case, when the list was modified, I retrieved the selected index and stored the object that was selected before updating the list. After the list is modified and before the table is updated, I would calculate the position of the selected object. If it was still present after the modification, then I would set the selection to the new index.
Just setting the selected index in the table after the modification will not work, because the object may change position in the list.
As a side note, I found that working with GlazedLists makes life much easier when dealing with tables.
This is default behavior. If you call fireTableDataChanged() the entire table is rebuild from scratch as you set entirely new model. In this case the selection is, naturally, lost. If you call fireTableRowsUpdated() the selection is also cleared in general cases. The only way is to remember selection and then set this. Unfortunately there is no guarantee that the selection will be still valid. Be careful if restoring selection.
for reference, as #Swapnonil Mukherjee stated, this did the trick with a table with selectable rows:
// preserve selection calling fireTableDataChanged()
final int[] sel = table.getSelectedRows();
fireTableDataChanged();
for (int i=0; i<sel.length; i++)
table.getSelectionModel().addSelectionInterval(sel[i], sel[i]);
If I recall correctly, saving selection and re-applying it is what we have done too...
I was facing same issue and when tried to search the reason I got this question but it seems a bug in Java SDK. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4276786
WORK AROUND
A temporary work-around is available. It should be removed once this bug is fixed as it's suitability has NOT been tested against fixed releases.
Use this subclass of JTable.
Note: This is for the MetalLookAndFeel. If using other look and feels, the inner FixedTableUI subclass will have to extend the TableUI subclass for that look and feel.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
public class FixedTable extends JTable {
private boolean isControlDownInDrag;
public FixedTable(TableModel model) {
super(model);
setUI(new FixedTableUI());
}
private class FixedTableUI extends BasicTableUI {
private MouseInputHandler handler = new MouseInputHandler() {
public void mouseDragged(MouseEvent e) {
if (e.isControlDown()) {
isControlDownInDrag = true;
}
super.mouseDragged(e);
}
public void mousePressed(MouseEvent e) {
isControlDownInDrag = false;
super.mousePressed(e);
}
public void mouseReleased(MouseEvent e) {
isControlDownInDrag = false;
super.mouseReleased(e);
}
};
protected MouseInputListener createMouseInputListener() {
return handler;
}
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if (isControlDownInDrag) {
ListSelectionModel rsm = getSelectionModel();
ListSelectionModel csm = getColumnModel().getSelectionModel();
int anchorRow = rsm.getAnchorSelectionIndex();
int anchorCol = csm.getAnchorSelectionIndex();
boolean anchorSelected = isCellSelected(anchorRow, anchorCol);
if (anchorSelected) {
rsm.addSelectionInterval(anchorRow, rowIndex);
csm.addSelectionInterval(anchorCol, columnIndex);
} else {
rsm.removeSelectionInterval(anchorRow, rowIndex);
csm.removeSelectionInterval(anchorCol, columnIndex);
}
if (getAutoscrolls()) {
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
if (cellRect != null) {
scrollRectToVisible(cellRect);
}
}
} else {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
}
}
Note Curtsey to http://bugs.sun.com