Created
May 17, 2011 14:10
-
-
Save exhuma/976531 to your computer and use it in GitHub Desktop.
Avoid focus on non-editable cells in a JTable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package lu.statec.gui.blaise; | |
import java.awt.event.KeyEvent; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import javax.swing.JComponent; | |
import javax.swing.KeyStroke; | |
import javax.swing.table.TableModel; | |
import org.jdesktop.swingx.JXTable; | |
/** | |
* This table overrides the selection behavior. If the selection happens to land | |
* on a non-editable cell, the selection is forwarded to the next editable cell. | |
* | |
* Additionally, the "Enter"/"Return" key is rebound, so it selects the next | |
* cell instead of next row. | |
* | |
* NOTE: | |
* It extends JXTable from swingx. This is for convenience only. If you don't | |
* have or want to use swingx, you can simply replace it with a simple JTable | |
* in the class definition. | |
* | |
* Original idea by Joe Knapka can be found at: | |
* http://www.javakb.com/Uwe/Forum.aspx/java-gui/3796/Cell-focus-in-JTable-avoid-focus-on-non-editable-cells | |
* | |
* @author Michel Albert | |
*/ | |
public class QuickEditTable extends JXTable { | |
public static enum DIR { | |
Up, Down, Left, Right | |
} | |
/** | |
* The logger | |
*/ | |
private static final Logger LOG = Logger.getLogger(QuickEditTable.class.getCanonicalName()); | |
/** | |
* Standard constructor | |
*/ | |
public QuickEditTable() { | |
init(); | |
} | |
/** | |
* Default constructor, initialising the table with a TableModel | |
* | |
* @param tableModel | |
*/ | |
public QuickEditTable(TableModel tableModel) { | |
super(tableModel); | |
init(); | |
} | |
/** | |
* Initialisations common to all constructors. | |
*/ | |
private void init() { | |
// When pressing enter, move to the next cell instead of the next row. | |
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) | |
.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "selectNextColumnCell"); | |
} | |
@Override | |
public void changeSelection(int row, int col, boolean toggle, boolean expand) { | |
// This method is called when the user tries to move to a different cell. | |
// If the cell they're trying to move to is not editable, we look for | |
// the next cell in the proper direction that is editable. | |
// initialise the new (future) selection to the indices as specified in | |
// the method call. | |
// if everything is "normal" we can just use these values. All special | |
// cases will overwrite the value contained herein. Eventually, these | |
// variables are returned. | |
int targetViewRow = row; | |
int targetViewCol = col; | |
int targetModelRow = convertRowIndexToModel(targetViewRow); | |
int targetModelCol = convertColumnIndexToModel(targetViewCol); | |
if (LOG.isLoggable(Level.FINE)){ | |
LOG.fine(String.format("Attempting to change the table selection " | |
+ "to row %d, col %d, using toggle=%b and expand=%b", | |
targetViewRow, targetViewCol, toggle, expand)); | |
LOG.fine(String.format(" --> this maps to model row %d and col %d", | |
targetModelRow, targetModelCol)); | |
} | |
if (!getModel().isCellEditable(targetModelRow, targetModelCol)) { | |
if (LOG.isLoggable(Level.FINE)){ | |
LOG.fine(String.format("Cell %d,%d (%d,%d) is not editable!", | |
targetViewRow, targetViewCol, targetModelRow, targetModelCol)); | |
} | |
// Find the row and column we're coming from. | |
int oldViewRow = getEditingRow(); | |
int oldViewCol = getEditingColumn(); | |
if (oldViewRow == -1) { | |
oldViewRow = getSelectedRow(); | |
} | |
if (oldViewCol == -1) { | |
oldViewCol = getSelectedColumn(); | |
} | |
if (LOG.isLoggable(Level.FINE)) { | |
LOG.fine(String.format("We came from cell %d,%d", | |
oldViewRow, oldViewCol)); | |
} | |
DIR direction; | |
if (oldViewCol == targetViewCol && oldViewRow < targetViewRow) { | |
direction = DIR.Down; | |
} else if (oldViewCol == targetViewCol && oldViewRow >= targetViewRow) { | |
direction = DIR.Up; | |
} else if (oldViewCol == targetViewCol && oldViewRow == targetViewRow) { | |
direction = DIR.Left; | |
} else { | |
// defaulting to right | |
direction = DIR.Right; | |
} | |
LOG.fine(String.format("Moving %s", direction)); | |
// determine next cell position | |
while (!getModel().isCellEditable(targetModelRow, targetModelCol)) { | |
LOG.fine(String.format("Model-Cell %d,%d is still not editable", | |
targetModelRow, targetModelCol)); | |
switch (direction) { | |
case Up: | |
targetViewRow -= 1; | |
if (targetViewRow < 0) { | |
targetViewRow = getRowCount() - 1; | |
} | |
break; | |
case Down: | |
targetViewRow += 1; | |
if (targetViewRow > getRowCount() - 1) { | |
targetViewRow = 0; | |
} | |
break; | |
case Left: | |
targetViewCol -= 1; | |
if (targetViewCol < 0) { | |
targetViewCol = getRowCount() - 1; | |
targetViewRow -= 1; | |
if (targetViewRow < 0) { | |
targetViewRow = getRowCount() - 1; | |
} | |
} | |
break; | |
case Right: | |
targetViewCol += 1; | |
if (targetViewCol > getColumnCount() - 1) { | |
targetViewCol = 0; | |
targetViewRow += 1; | |
if (targetViewRow > getRowCount() - 1) { | |
targetViewRow = 0; | |
} | |
} | |
break; | |
} | |
targetModelRow = convertRowIndexToModel(targetViewRow); | |
targetModelCol = convertColumnIndexToModel(targetViewCol); | |
} | |
LOG.fine(String.format("Trying to move selection to %d,%d instead!", | |
targetViewRow, targetViewCol)); | |
} | |
super.changeSelection(targetViewRow, targetViewCol, toggle, expand); | |
} | |
} |
And modelÑ
DefaultTableModel model = new DefaultTableModel(null,col);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello, it's a great pleasure to say hello, I do not speak or write in English and I apologize if it does not read well since I use Google translation, I'm a Java beginner and I do not know how to start this class to use a JFrame, I have a project at the university and they ask me to do what they implemented in this class. I do not know if you could help me use your class from a jframe that has a table to evaluate the cells when they have the focus, thanks in advance.
I use the Netbeans IDE and the table is created graphically, not by code, my question is how do I apply its class to the table that I create graphically. So I have tried but it does not work for me:
Object [] col = {"Sku", "Descripcon", "Measure", "Quantity", "Price", "SubTotal"};
// this table is the one I have created from the graphic environment and here I assign it to its class but it does not work
table = new CustomSelectTable (model);
I do not know how it would be the correct way to implement your class to the JTable that you create.