I have written a "double-click" event on my JTable. My JTable, viz. myTaskTable is populated with a number of rows having multiple columns. I want the row index to be retrieved when I double click on one of the rows of the JTable. I am not sure why is it always returning me an index of -1 resulting in an exception. Am I am overlooking something? What could be going wrong?
This is how I am retrieving the index of the selected row from the JTable - myTaskTable
int selRow = myTaskTable.getSelectedRow();
Thank you!
Edit
Here is the code:
...
myTaskTable.addMouseListener(this);
...
public void mouseClicked(MouseEvent e)
{
if(e.getModifiers() == MouseEvent.BUTTON1_MASK)
{
if(e.getClickCount() == 2)
{
e.consume();
int selRow = myTaskTable.getSelectedRow();
System.out.println("GridReport double clicked on row="+selRow);
}
}
}
Get the row index using the event, not the table selection:
final int selectedRowIndex = table.rowAtPoint(mouseEvent.getPoint());
// If the rows are sorted or filtered
final int modelRowIndex = table.convertRowIndexToModel(selectedRowIndex);
getSelectedRow() would not work with multiple selected rows (multiple selections allowed), as it will always return "the index of the first selected row".
have you tried to put e.consume(); as the last statement?
public void mouseClicked(MouseEvent e){
if(e.getModifiers() == MouseEvent.BUTTON1_MASK){
if(e.getClickCount() == 2){
int selRow = myTaskTable.getSelectedRow();
System.out.println("GridReport double clicked on row="+selRow);
e.consume();
}
}
}
normaly e.consume(); is called when you are done with your reactive code. This clears dependencies of the Event, so it might also clear the selected Row.
Related
I have a Jtable set up in a tabbed pane that is filled with an id and checkboxes. The table looks something along the lines of this, where . are the checkboxes.
| VAR1 |
ID | ALL | subVar1 | subVar2 |
------------------------------
id1| . | . | . |
Now, I also have a TableListener attached to this table. What I would like to happen is that, whenever a user presses the ALL checkbox, all the checkboxes in that row need to be selected (ie true). This is the table listener code.
#Override
public void tableChanged(TableModelEvent e) {
if(e.getSource() == assignedTableModel) {
for (int i = 0; i < aTable.getRowCount(); i++) {
boolean isAllChecked = (Boolean) aTable.getValueAt(i, 1);
if(isAllChecked) {
assignedTableModel.setValueAt(Boolean.TRUE, i, j);
}
else {
...
}
}
}
}
Clicking the ALL checkbox causing the table to change, assignedTableModel.setValueAt(Boolean.TRUE, i, j); is called, the table is changed again and therefore calls the listener, which calls this function again.
My question, is there another way of updating the checkboxes? Or is there a way to set a base to get out of the recursion?
EDIT The rows are added dynamically. I'm wondering if adding an actionListener to the ALL checkbox as it's being added will be a solution. I'll come back with how it turns out.
EDIT2 I'd forgot to mention that the whole table is generated dynamically. That means I have no way of knowing how many columns and rows will be present, the only columns I know are ID and the ALL col. Most answers already present deal with hard coded implementations.
whenever a user presses the ALL checkbox, all the checkboxes in that row are selected
So why are you looping through all the rows in your code? The event will be generated only for the row you click and you only need to select the check marks for the columns on that row. Get rid of the looping code.
the table is changed again and therefore calls the listener, which calls this function again.
You need an if condition to identify when the check box in the first column is checked:
if (e.getType() == TableModelEvent.UPDATE)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 0)
{
TableModel model = (TableModel)e.getSource();
model.setValueAt(Boolean.true, row, 1);
...
}
}
Now the change of state on the other columns will be ignored.
Based off of #camickr's response, the following piece of code seems to be doing the trick. Thanks.
#Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.UPDATE && e.getSource() == assignedTableModel)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 1)
{
DefaultTableModel model = (DefaultTableModel) e.getSource();
for(int i=2 ; i<model.getColumnCount() ; i++) {
if((boolean) model.getValueAt(row, 1))
model.setValueAt(Boolean.TRUE, row, i);
else
model.setValueAt(Boolean.FALSE, row, i);
}
}
}
}
I am working on doing a word finder puzzle game. When I am trying to get to happen is a user clicks on a letter then moves his mouse across other letters to create a word. I am having some problems with the listeners. I have been going back and fourth using mouseDragged and mouseMoved. So far mouseMoved seems to work better because it dynamically grabs values. The problem is I can't figure out how to get it only grab one value. In an ideal world it would move of a Button or label grab that value once and ignore the value till it reaches a new button or label. Currently it just grabs values at every instant a mouse is on that container. The logic for my Mouse method is below:
public void mouseMoved(MouseEvent e) {
int count = countClicked;
int num = 0;
for(JToggleButton row : puzzleGrid){
if(e.getComponent() == row && count == 1) {
if(num == 0){
num++;
for(JLabel l: solWords)
{
sb.append(row.getText());
System.out.println(l.getText()+" = "+ sb.toString());
if(l.getText().contentEquals(row.getText()))
System.out.println(row.getText());
}
}
}
}
}
I am using the value gathered from the containers to check against an array of JLabels containing the solution values.
You could store the last letter in a static variable:
static String lastLetter = null;
mouseMoved(...) {
if(row.getText().equals(lastLetter)) {
continue;
}
lastLetter = row.getText();
}
table.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
if(table.getSelectionIndex() != -1)
{
System.out.println(table.getSelectionIndex());
TableItem item = table.getItem(table.getSelectionIndex());
System.out.println(item.toString());
}
else
{}
}
});
when i click on any cell in my table, only the first cell of that row is selected and returned and not exactly that cell
please tell me how can i select and get item from exactly that cell which i select
please see the image
i have selected 3rd column but it returned the TableItem of first column
I encountered the same problem before, and this is how I solved it:
First, you should make the table SWT.FULL_SELECTION`;
Then, you have to get the selected cell by reading the mouse position (because the basic swt table does not provide listeners to get selected cell; select a item is possible). Here is the code:
table.addListener(SWT.MouseDown, new Listener(){
public void handleEvent(Event event){
Point pt = new Point(event.x, event.y);
TableItem item = table.getItem(pt);
if(item != null) {
for (int col = 0; col < table.getColumnCount(); col++) {
Rectangle rect = item.getBounds(col);
if (rect.contains(pt)) {
System.out.println("item clicked.");
System.out.println("column is " + col);
}
}
}
}
});
I was facing a similar problem with nebula grid and found out that you have to enable cell selection on the table object. Here is my code line:
tableViewer.getGrid().setCellSelectionEnabled(true);
Perhaps it you could try to replace getGrid() by getTable(). You will not need to implement the selection listener for this.
I am having problems with a popup menu on a JTable and the fact that this JTable allows for Multiple Interval Selection.
I'm going to explain in detail my situation, making it as clear as possible, hopefully.
I have a basic data class, lets call it Item, with a string id (name) and two boolean fields, online and active (with relative getters).
The idea behind the JTable is that, for each item in the dataset, it will show its name in the first colum and its status in the second column, where by 'status' I mean that, it will show "ACTIVE/NOT ACTIVE" if the Item is Online, otherwise it will show "OFFLINE".
I have implemented a TableModel that does the job and it works.
I also want, when the user right clicks on a row, a popup to appear (if the selected Item is ONLINE) allowing to Activate/Deactivate the item, depending on its status.
This worked perfectly as long as the Selection Model was SINGLE SELECTION, but when I changed it to MULTIPLE INTERVALS SELECTION, I could not make it work properly anymore.
The behaviour that I want is that, on right-click, a popup appears where the click is performed, the row is added to the selection and highlighted and all the previously selected rows stay selected! This I cannot manage to do!
Here is the code I have in the MouseListener:
tblModel.addMouseListener(new MouseAdapter() {
void showPopup(MouseEvent e){
int r = tblModel.rowAtPoint(e.getPoint());
if (r >= 0 && r < tblModel.getRowCount()) {
//tblModel.setRowSelectionInterval(r, r);
} else {
tblModel.clearSelection();
}
int[] viewRowIndexes = tblModel.getSelectedRows();
int rowViewIndex = tblModel.getSelectedRow();
if (rowViewIndex < 0)
return;
int rowModelIndex = tblModel.convertRowIndexToModel(rowViewIndex);
if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
Action changeActiveAction;
Action changeInactiveAction;
List<String> actives = new ArrayList<String>();
List<String> inactives = new ArrayList<String>();
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) tblModel.getSelectionModel();
for (int viewRowIndex : viewRowIndexes) {
int modelRowIndex = tblModel.convertRowIndexToModel(viewRowIndex);
if (selectionModel.isSelectedIndex(viewRowIndex)) {
boolean online = ((MyTableModel) tblModel.getModel()).isItemOnline(modelRowIndex);
if (!online)
continue;
boolean active = ((MyTableModel) tblModel.getModel()).isItemActive(modelRowIndex);
String idItem = (String) ((MyTableModel) tblModel.getModel()).getValueAt(modelRowIndex,0);
if (active) {
actives.add(idItem);
} else {
inactives.add(idItem);
}
}
}
if (actives.size() > 0 || inactives.size() > 0) {
popup = new JPopupMenu();
if (actives.size() > 0) {
changeActiveAction = new ChangeAction("Deactivate ACTIVE Items","This will deactivate all the selected ACTIVE items",actives, false);
popup.add(new JMenuItem(changeActiveAction));
}
if (inactives.size() > 0) {
changeInactiveAction = new ChangeAction("Activate INACTIVE Items","This will activate all the selected INACTIVE items",inactives, true);
popup.add(new JMenuItem(changeInactiveAction));
}
popup.show(e.getComponent(), e.getX(),e.getY());
}
}
}
#Override
public void mousePressed(MouseEvent e) {
showPopup(e);
}
#Override
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
};
The behaviour is functionally correct, but the selection of rows is not working.
Having commented the line
//tblModel.setRowSelectionInterval(r, r);
when I right-click on a row, a popup appears, but it ignores the row on which I clicked.
On the other hand, if uncommented, that line will select only the clicked row, losing all the rest of the selection....
I am sorry for the long post, but I didn't know how to explain my problem without giving all the details of my situation....
Hopefully this is a trivial thing and you can tell me how I can fix/change it.
Thank you in advance.
One part of the answer is:
if (tblModel.isSelectedIndex(r)) {
tblModel.removeSelectionInterval(r, r);
} else {
tblModel.addSelectionInterval(r, r);
}
I have a column with plain text in it.
If the user double-clicks a row in that column, the column allows itself to be edited for that row (as it should).
I need something to detect when that text is done with being edited (when the user hits the enter key, for example). When that happens, I need something to get the row ID of that change (0-based of course).
Any ideas?
Thanks!
You should add a listener to the TableModel:
table.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
// your code goes here;
}
});
TableModelEvent contains row and column number and type of modification.
I think the easiest way to get the location of the click in terms of row and column would be this:
table.addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int column = table.columnAtPoint(e.getPoint());
if (row >= 0 && column >= 0) {
......
}
}
});