JTextField.selectAll() works strangely - java

I'm trying to implement a JTable which has to obey the following rules:
Only the 3'rd column's cells can be edited.
When double clicking any cell in row X, the 3'rd column of row X will start edit.
Whenever start editing a cell, the text inside of it will be selected.
I have a FileTable which extends JTable. In its constructor I have this lines:
getColumnModel().getColumn(2).setCellEditor(new FileTableCellEditor());
addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if (e.getClickCount() == 2){
int row = rowAtPoint(e.getPoint());
editCellAt(row, 2);
}
}
} );
My FileTableCell editor is as follows:
public class FileTableCellEditor extends DefaultCellEditor {
public FileTableCellEditor() {
super(new JTextField());
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
final JTextField ec = (JTextField) editorComponent;
String textValue = (String)value;
ec.setText(textValue);
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
ec.selectAll();
}
});
return editorComponent;
}
}
My problem is when I double click on a cell which is not from the 3'rd column, The text edited on the 3'rd columns is not highlighted as selected text.
picture http://www.nispahit.com/stack/tableNotHighlight.png
This is very odd to me, because I know the text is selected. When I write something it removes the text that was in that cell before. It just doesn't what is selected.
Oddly, when I double click the 3'rd column cell itself, it does highlight the selection.
picture http://www.nispahit.com/stack/tableHighlight.png
Can someone pour some light?
Thanks!

You can try the Table Select All Editor approach. Don't forget to check out the Table Select All Renderer.

Your JTextField does not highlight the selection because it is not focused. Just add a ec.requestFocus(); right after ec.selectAll();. Then it works as expected.
Explanation: When you click on the editable column Swing will start cell editing (independently of your double-click listener) and forward the initiating event to the component. So the JTextField receives a click and will request focus. When you click on a different column, only your MouseListener initiates cell editing and the event will not get forwarded. (Forwarding the event would not help anyway as the click is outside the text field.) So you have to request the focus manually.

Related

Change behavior of JTable key actions

I have a JTable with editable cells. When I click in a cell, it enters edit mode; the same happens when I'm moving through cell using the directional arrows.
Now I want to select the cell instead of start editing, and edit the cell only when the Enter key is pressed.
If any other information is needed, please just ask for it.
Edit: Action for Enter key
class EnterAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
JTable tbl = (JTable) e.getSource();
tbl.editCellAt(tbl.getSelectedRow(), tbl.getSelectedColumn());
if (tbl.getEditorComponent() != null) {
tbl.getEditorComponent().requestFocus();
}
}
}
Now this is for left arrow action the rest of 3 are not hard to deduce from this one:
class LeftAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
JTable tbl = (JTable)e.getSource();
tbl.requestFocus();
tbl.changeSelection(tbl.getSelectedRow(), tbl.getSelectedColumn() > 0 ? tbl.getSelectedColumn()-1:tbl.getSelectedColumn(), false, false);
if(tbl.getCellEditor()!=null)
tbl.getCellEditor().stopCellEditing();
}
}
And this is how you bind this actions:
final String solve = "Solve";
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(enter, solve);
table.getActionMap().put(solve, new EnterAction());
final String sel = "Sel";
KeyStroke arrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(arrow, sel);
table.getActionMap().put(sel, new LeftAction());
Oh,i almost forgot,to select the cell instead of edit on Mouse Click:
public static MouseListener mAdapterTable = new MouseListener()
{
#Override
public void mousePressed(MouseEvent e)
{
JTable tbl=((JTable)e.getComponent());
if(tbl.isEditing())
{
tbl.getCellEditor().stopCellEditing();
}
}
#Override
public void mouseClicked(MouseEvent e) {
JTable tbl=((JTable)e.getComponent());
if(tbl.isEditing() )
tbl.getCellEditor().stopCellEditing();
}
#Override
public void mouseReleased(MouseEvent e) {
JTable tbl=((JTable)e.getComponent());
if(tbl.isEditing() )
tbl.getCellEditor().stopCellEditing();
}
};
The EventListner must be added to table like so:
table.addMouseListener(mAdapterTable);
Use Key Bindings for this. Most Look & Feel implementations already bind F2 to the table's startEditing action, but you add a different binding:
tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "startEditing");
This will effectively replace the previous binding of Enter to the table's selectNextRowCell action.
Here is what i would do:
First enable the single cell selection for the JTable
Create a KeyAdapter or KeyListener for the JTable or for the JPanel,
what contains your table.
In the KeyAdapter's keyPressed() method enter the edit mode of the
selected cell, something like this:
http://www.exampledepot.com/egs/javax.swing.table/StopEdit.html
You can check in the keyPressed() method, if the user pressed the right button for editing. I'm not sure, if the normal (double click) editing is disabled in your table, then what happens, if you try to edit it programmatically, but if it doesn't work, then you can enable the editing on the selected cell, when the user presses the edit button, then when he/she finished, disable it again.

Using JComboBox as Cell Editor in JTable and saving changes

I am using a JComboBox as a cell editor for my JTable. When I select one of the values from the drop down list of the ComboBox, setValueAt is not getting called. I know this because I have overridden the function. Based on the value selected in this cell, the value in another cell of the same table is fixed. Also, I need to know which is the actionListener for this event, i.e when I change the value in the ComboBox.
The setValueAt does get called only when the focus is changed to another cell in the table, just clicking outside the table also does not help.
#Override
public void setValueAt(Object o,int row,int col)
{
super.setValueAt(o, row, col);
if(((String)o).matches("1"))
{
super.setValueAt(o, col-1, row+1);
return;
}
if(((String)o).contains("/"))
super.setValueAt(((String)o).substring(2), col-1, row+1);
else
super.setValueAt("1/"+(String)o, col-1, row+1);
}
I just found the way...
I need to add an actionListener to the JComboBox component that I created as a member of the CellEditor class and in the listener function, i need to call stopCellEditing so that the setValueAt gets called...

Adding actionlistener of column in a jtable

Hi everyone..
I need some help again. :)
How to do this? When I click the column t1, another form must pop-up explaining what happens to column t1, say, at time 1, Instruction 1 is in fetch stage. Then, when I click naman t2 column, Instruction 2 is in fetch stage and Instruction 1 is in Decode stage., so on and so forth.
Thank you in advance. I really need your help..
Regards.. :)
You need to add following chunk of code,
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// This is for double click event on anywhere on JTable
if (e.getClickCount() == 2) {
JTable target = (JTable) e.getSource();
int row = target.getSelectedRow();
int column = target.getSelectedColumn();
// you can play more here to get that cell value and all
new DialogYouWantToOpen(row, Column);
}
}
});
A Dialog which will be opened on double click.
class DialogYouWantToOpen extends JDialog{
JLabel testLabel = new JLable();
public DialogYouWantToOpen(int row, int column){
setSize(200,200)
setLayout(new FlowLayout());
testLabel.setText("User double clicked at row "+row+" and column "+ column);
add(testLabel);
}
}
Generaly it should go something like this
Listener listener = new Listener() {
public void handleEvent(Event e) {
TableColumn column = (TableColumn) e.widget;
System.out.println(column);
}
};
you get the column out of event and then do what you want with it.

How to dismiss all tooltips in table when cell editing begins?

I have enabled tooltips in my JTable by overriding the JComponent method that the JTable inherits:
public String getToolTipText(MouseEvent e) { ... }
Now, suppose a user hovers over a cell, the tooltip appears, and then (s)he starts editing the cell, I want to forcefully dismiss the tooltip.
Currently, the tooltip just hangs around until the value that I specified using ToolTipManager#setDismissDelay expires. The tooltip can sometimes obscure the view of the cell being edited which is why I want to dismiss it the moment any cell on the table goes into edit mode.
I tried the following approach (this is pseudo-code)
public String getToolTipText(MouseEvent e)
{
if(table-is-editing)
return null;
else
return a-string-to-display-in-the-tooltip;
}
Of course, this only had the effect of NOT showing tooltips of the table is ALREADY in edit mode. I knew this wouldn't work, but it was more of a shot in the dark.
You can show/hide a tooltip by using code like:
//Action toolTipAction = component.getActionMap().get("postTip");
Action toolTipAction = component.getActionMap().get("hideTip");
if (toolTipAction != null)
{
ActionEvent ae = new ActionEvent(component, ActionEvent.ACTION_PERFORMED, "");
toolTipAction.actionPerformed( ae );
}
You couuld probably override the prepareCellEditor(...) method of JTable to add this code and it should hide any tooltip before displaying the editor.
Edit:
In response to Kleopatra's comment I then add the following to make sure the Action is added to the ActionMap:
table.getInputMap().put(KeyStroke.getKeyStroke("pressed F2"), "dummy");
ToolTipManager.sharedInstance().registerComponent( table );
Was about to comment "something wrong with your" - but remembered a use case when not hiding the Tooltip on starting edits may happen :-)
Some facts:
tooltips are hidden on mouseExit and on focusLost the component which is registered with the ToolTipManager
when starting an edit and the editing component gets focus so the tooltip is hidden automatically
by default, JTable does not yield focus to the editing component is the editing is started by typing into the cell (as opposed by double-click or F2): in this case no focusLost is fired and consequently the tooltip not hidden
the ToolTipManager indeed installs a hideAction which might be re-used (as #camickr mentioned). But - that action is installed only if the component has a inputMap of type WHEN_FOCUSED. Which is not the case for JTable (all its bindings are in WHEN_ANCESTOR)
So it requires a handful of tweaks to implement the required behaviour, below is a code snippet (note to myself: implement in SwingX :-)
JTable table = new JTable(new AncientSwingTeam()) {
{
// force the TooltipManager to install the hide action
getInputMap().put(KeyStroke.getKeyStroke("ctrl A"),
"just some dummy binding in the focused InputMap");
ToolTipManager.sharedInstance().registerComponent(this);
}
#Override
public boolean editCellAt(int row, int column, EventObject e) {
boolean editing = super.editCellAt(row, column, e);
if (editing && hasFocus()) {
hideToolTip();
}
return editing;
}
private void hideToolTip() {
Action action = getActionMap().get("hideTip");
if (action != null) {
action.actionPerformed(new ActionEvent(
this, ActionEvent.ACTION_PERFORMED, "myName"));
}
}
};
Check out this JTable tutorial. In particular this webstart. There are two editable columns with tooltips - 'Sport' and 'Vegetarian' work just fine. Are you using any custom cell renderers?
This worked for me and seems simpler than using an action:
ToolTipManager.sharedInstance().mouseExited(new MouseEvent(myJframe, 0, 0, 0, 0, 0, 0, 0, 0, false, 0));
This seems to hide any tooltip shown inside the specified JFrame.
With JDK 1.6, when a cell tooltip is being displayed, the user cannot extend the range of selected rows using the keyboard. The solution presented above worked very nicely for that problem as well. Here is the code:
public class ToolTipTable extends JTable
{
/**
* Constructor
*/
public ToolTipTable()
{
super();
// force the TooltipManager to install the hide action
getInputMap().put(KeyStroke.getKeyStroke("ctrl A"),
"just some dummy binding in the focused InputMap");
ToolTipManager.sharedInstance().registerComponent(this);
//hide the tool tip when row selection changes
this.getSelectionModel().addListSelectionListener(
new ListSelectionListener()
{
#Override
public void valueChanged(ListSelectionEvent e)
{
hideToolTip();
}
});
}
/**
* Make the cell tool tip show the contents of the cell. (Useful if the
* cell contents are wider than the column.)
*/
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row,
int column)
{
Component c = super.prepareRenderer(renderer, row, column);
if (c instanceof JComponent)
{
JComponent jc = (JComponent) c;
Object valueObj = getValueAt(row, column);
if (valueObj != null)
{
jc.setToolTipText(getValueAt(row, column).toString());
}
}
return c;
}
/**
*
*/
private void hideToolTip()
{
Action action = getActionMap().get("hideTip");
if (action != null)
{
action.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED, "myName"));
}
}
}

How can I make a JTable cell do different things on single-click than on double-click?

I am using an editable JTable that contains a column named Subject. When the first row is empty and the user clicks on a subject cell to add new task, by default, the user has to click twice to make the cell editable. I want to make it editable on single-click and have it open another form on double-click. I have tried MouseListener but have not been able to solve it. Is there a way to solve this problem? If so, what is it?
My code:
class mouseRenderer extends DefaultTableCellRenderer {
JLabel lblcell = new JLabel();
public Component getTableCellRendererComponent(JTable table, Object obj, boolean isSelected, boolean hasFocus, int row,
int column) {
ttable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
selrow = ttable.getSelectedRow();
selcol = ttable.getSelectedColumn();
if(e.getClickCount() == 1) {
if(selrow == 0) {
lblcell.setText("");
}
}
}
});
return lblcell;
}
}
For the one-click to edit, you could try the 'setClickCountToStart()' method of the celleditor used in your jtable.
You can try to create a custom CellEditor like this one and set it with setCellEditor()
public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
public boolean isCellEditable(EventObject evt) {
if (evt instanceof MouseEvent) {
int clickCount;
// For single-click activation
clickCount = 1;
// For double-click activation
clickCount = 2;
// For triple-click activation
clickCount = 3;
return ((MouseEvent)evt).getClickCount() >= clickCount;
}
return true;
}
}
The MouseListener is the way to go for capturing double clicks on a row. It should work fine.
As far as one-click to edit, you might want to select rows using a MouseMotionListener and let the JTable take the single-click to edit. Another option might be to use a MouseListener to detect the cell that was clicked, but that is getting a little messy.

Categories