AppletTalk.com Forum Index AppletTalk.com
Java discussions newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problem with JTable and DefaultCellEditor

 
Post new topic   Reply to topic    AppletTalk.com Forum Index -> Java GUI Toolkits
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Wed May 24, 2006 10:07 pm    Post subject: Problem with JTable and DefaultCellEditor Reply with quote



I have a JTable with editable columns, some of which should accept only
numbers. To do this, I have added a DefaultCellEditor to the numeric
columns, with a JTextField to accept user input, and a KeyListener to
filter out non-numeric keystrokes from the JTextField.

The user can start editing by mouse-clicking in a cell and typing, or
by navigating around the table using the arrow keys, then type in a
cell, without using the mouse.

All this works well, except in the second case when the user types in a
cell without first selecting it with the mouse. The problem here is
that the KeyListener does not see the first keystroke, but does see
subsequent ones. That means one non-numeric character can be entered
into the cell. However, the KeyListener always works if the user first
selects the cell with a mouse-click. Below is some code showing this
behaviour. What am I missing? How can I capture that first keystroke? I
am using Java 1.5.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class Test extends JFrame {
public Test() {
JTable table = new JTable(new Object[][] { {"a",1,2},{"b",3,4} },
new String[] {"Text", "Num 1", "Num 2"});
table.setRowSelectionAllowed(false);
table.setSurrendersFocusOnKeystroke(true);

TableColumnModel cm = table.getColumnModel();
cm.getColumn(1).setCellEditor(new MyCellEditor());
cm.getColumn(2).setCellEditor(new MyCellEditor());

JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
}

private class MyCellEditor extends DefaultCellEditor {
private final JTextField tf;

public MyCellEditor() {
super(new JTextField());
tf = (JTextField) getComponent();
tf.addKeyListener(new MyKeyListener ());
setClickCountToStart(1);
}

public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
tf.setText(value.toString());
return tf;
}

public Object getCellEditorValue() {
return tf.getText();
}
}

private class MyKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {
if ( ! Character.isDigit(e.getKeyChar()) ) {
Toolkit.getDefaultToolkit().beep();
e.consume();
}
}
}

public static void main(String[] args) {
Test frame = new Test();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Mike
Back to top
Vova Reznik
Guest





PostPosted: Thu May 25, 2006 2:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote



michael.o'connor (AT) bluescopesteel (DOT) com wrote:
Quote:
I have a JTable with editable columns, some of which should accept only
numbers. To do this, I have added a DefaultCellEditor to the numeric
columns, with a JTextField to accept user input, and a KeyListener to
filter out non-numeric keystrokes from the JTextField.

The user can start editing by mouse-clicking in a cell and typing, or
by navigating around the table using the arrow keys, then type in a
cell, without using the mouse.

All this works well, except in the second case when the user types in a
cell without first selecting it with the mouse. The problem here is
that the KeyListener does not see the first keystroke, but does see
subsequent ones. That means one non-numeric character can be entered
into the cell. However, the KeyListener always works if the user first
selects the cell with a mouse-click. Below is some code showing this
behaviour. What am I missing? How can I capture that first keystroke? I
am using Java 1.5.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class Test extends JFrame {
public Test() {
JTable table = new JTable(new Object[][] { {"a",1,2},{"b",3,4} },

{"a",1,2},{"b",3,4} - ??

Quote:
new String[] {"Text", "Num 1", "Num 2"});
table.setRowSelectionAllowed(false);
table.setSurrendersFocusOnKeystroke(true);

TableColumnModel cm = table.getColumnModel();
cm.getColumn(1).setCellEditor(new MyCellEditor());
cm.getColumn(2).setCellEditor(new MyCellEditor());

JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
}

private class MyCellEditor extends DefaultCellEditor {
private final JTextField tf;

public MyCellEditor() {
super(new JTextField());
tf = (JTextField) getComponent();
tf.addKeyListener(new MyKeyListener ());
setClickCountToStart(1);
}

public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
tf.setText(value.toString());
return tf;
}

public Object getCellEditorValue() {
return tf.getText();
}
}

private class MyKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {
if ( ! Character.isDigit(e.getKeyChar()) ) {
Toolkit.getDefaultToolkit().beep();
e.consume();
}
}
}

public static void main(String[] args) {
Test frame = new Test();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Mike


You don't need custom editor and KeyListener
(but if you want you'd better to use JFormattedTextField which
you may pass to a constructor of DefaultCellEditor).

You may create your own TableModel where you need to override
getColumnClass and your table will know what to do.

Your class back (different name) with custom table model.

import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class NumericColumnTester extends JFrame {

public NumericColumnTester() {
// JTable table = new JTable(new Object[][] {
// { "a", new Integer(1), "2" }, { "b", new Integer(3), "4" } },
// new String[] { "Text", "Num 1", "Num 2" });

String[]header = { "Text", "Num 1", "Num 2" };
List data = new ArrayList();
data.add(new Object[]{ "a", new Integer(1), "2" });
data.add(new Object[]{ "b", new Integer(3), "4" });
TableModel model = new TblModel(data, header);
JTable table = new JTable(model);
table.setRowSelectionAllowed(false);
table.setSurrendersFocusOnKeystroke(true);

// TableColumnModel cm = table.getColumnModel();
// cm.getColumn(1).setCellEditor(new MyCellEditor());
// cm.getColumn(2).setCellEditor(new MyCellEditor());

JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
}

private class MyCellEditor extends DefaultCellEditor {

private final JTextField tf;

public MyCellEditor() {
super(new JTextField());
tf = (JTextField) getComponent();
tf.addKeyListener(new MyKeyListener());
setClickCountToStart(1);
}

public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
tf.setText(value.toString());
return tf;
}

public Object getCellEditorValue() {
return tf.getText();
}
}

class TblModel extends AbstractTableModel {

private List data;
private String[] header;

public TblModel(List data, String[] header) {
this.data = data;
this.header = header;
}

public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1;
}

public int getColumnCount() {
return header == null ? 0 : header.length;
}

public int getRowCount() {
return data == null ? 0 : data.size();
}

public Object getValueAt(int rowIndex, int columnIndex) {
Object[] row = (Object[]) data.get(rowIndex);
return row[columnIndex];
}

public Class getColumnClass(int columnIndex) {
if (data == null) {
return Object.class;
}
Object[] row = (Object[]) data.get(0);
return row[columnIndex] == null ? Object.class :
row[columnIndex].getClass();
}

public String getColumnName(int column) {
return header[column];
}

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Object[] row = (Object[]) data.get(rowIndex);
row[columnIndex] = aValue;
super.fireTableCellUpdated(rowIndex, columnIndex);
}

}

private class MyKeyListener implements KeyListener {

public void keyPressed(KeyEvent e) {
}

public void keyReleased(KeyEvent e) {
}

public void keyTyped(KeyEvent e) {
if (!Character.isDigit(e.getKeyChar())) {
Toolkit.getDefaultToolkit().beep();
e.consume();
}
}
}

public static void main(String[] args) {
JFrame frame = new NumericColumnTester();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Back to top
bparanj
Guest





PostPosted: Thu May 25, 2006 4:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote



import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
import javax.swing.text.JTextComponent;

public class MyTable extends JTable {


public MyTable(TableModel dm) {
super(dm);
}

public Component prepareEditor(TableCellEditor editor,int row,int col)
{
JTextComponent comp = (JTextComponent)super.prepareEditor(editor,
row, col);
comp.setText(null);

return comp;
}

}

This code works. Do I need to provide other methods and delegate the
calls to JTable? Thanks.
BP
http://www.ProblemSolvingSkill.net
Back to top
Vova Reznik
Guest





PostPosted: Thu May 25, 2006 4:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote

bparanj wrote:
Quote:
I have a similar problem. But in my case, when the user starts editing
I want to be able to just clear out the old value and allow the user to
provide the new value. Is this possible? Thanks in advance.
BP.
http://www.ProblemSolvingSkill.net


override JTable#
public Component prepareEditor(TableCellEditor, int, int)

Component, if you didn't do your own, is always JTextComponent.

JTextComponent comp = super.prepareEditor(TableCellEditor, int, int);

comp.setText(null);

return comp;
Back to top
bparanj
Guest





PostPosted: Thu May 25, 2006 5:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote

Thanks. Actually two of my cells in my table allow numeric or hyphen
characters only. So I have been experimenting with your code. It seems
like that since the default implementation of JTable does not provide
the validation that checks if the entered value is numeric or hyphen, I
have to write my own custom editor right?

So if I do that, I am back to square one again. It is showing the first
character even if is not a legal character and then it starts beeping
and prevents entering of illegal characters. How do I resolve this
issue? Thanks for your time again!

BP
http://www.ProblemSolvingSkill.net
Back to top
Vova Reznik
Guest





PostPosted: Thu May 25, 2006 5:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote

bparanj wrote:
Quote:
import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
import javax.swing.text.JTextComponent;

public class MyTable extends JTable {


public MyTable(TableModel dm) {
super(dm);
}

public Component prepareEditor(TableCellEditor editor,int row,int col)
{
JTextComponent comp = (JTextComponent)super.prepareEditor(editor,
row, col);
comp.setText(null);

return comp;
}

}

This code works. Do I need to provide other methods and delegate the
calls to JTable? Thanks.
BP
http://www.ProblemSolvingSkill.net


It is your choice. May you will need another constructor or ...
I would add check if editor is JTextComponent.
Back to top
Vova Reznik
Guest





PostPosted: Thu May 25, 2006 5:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote

bparanj wrote:
Quote:
Thanks. Actually two of my cells in my table allow numeric or hyphen
characters only. So I have been experimenting with your code. It seems
like that since the default implementation of JTable does not provide
the validation that checks if the entered value is numeric or hyphen, I
have to write my own custom editor right?

So if I do that, I am back to square one again. It is showing the first
character even if is not a legal character and then it starts beeping
and prevents entering of illegal characters. How do I resolve this
issue? Thanks for your time again!

BP
http://www.ProblemSolvingSkill.net


Stay here and don't leave.
I'll write anything for you.
Back to top
steve
Guest





PostPosted: Thu May 25, 2006 11:07 pm    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote

On Fri, 26 May 2006 00:25:37 +0800, bparanj wrote
(in article <1148574337.708553.261140 (AT) j73g2000cwa (DOT) googlegroups.com>):

Quote:
Thanks. Actually two of my cells in my table allow numeric or hyphen
characters only. So I have been experimenting with your code. It seems
like that since the default implementation of JTable does not provide
the validation that checks if the entered value is numeric or hyphen, I
have to write my own custom editor right?

So if I do that, I am back to square one again. It is showing the first
character even if is not a legal character and then it starts beeping
and prevents entering of illegal characters. How do I resolve this
issue? Thanks for your time again!

BP
http://www.ProblemSolvingSkill.net


no the way to do it is to pass in a reg expression, that sets the formatting.
here is an example i use for formatting part numbers.

where you see the regexpression , is where you set the formatting option.
all you need to do is , change 1 line and that forces what the user may enter
into the text area.
just link the class into the table, and you will be forced to enter 1-15
characters.
Then all you need to do is play about to get the actual characters you want,
(just look at reg expression on google)





package utils.Validation;

import java.awt.Component;

import java.awt.event.ComponentListener;
import java.awt.event.FocusAdapter;

import java.awt.event.FocusEvent;

import javax.swing.DefaultCellEditor;
import javax.swing.JFormattedTextField;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultFormatterFactory;

import utils.RegexFormatter;

//this class validates a model number when it is edited in a table
//it is used both by the shipment shedule screen & the lc details screen!!





public class validateModelInTable extends DefaultCellEditor {
JFormattedTextField ftf;
public validateModelInTable(){
super(new JFormattedTextField());
ftf = (JFormattedTextField)getComponent();


//ensure every model number is atleast 1 char & no more than 15
//TODO
//we need to get this from the database in the calling class!!, instead of
getting it from a const.
//this should also be "Graph", not "Print" because we do not want to allow
spaces
RegexFormatter formatter =new RegexFormatter("\\p{Graph}{1,15}");

formatter.setOverwriteMode(false); //set it so shit inserts!!

ftf.setFormatterFactory(new DefaultFormatterFactory(formatter));





}

//Override to invoke setValue on the formatted text field.
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected,
int row, int column) {
JFormattedTextField ftf =
(JFormattedTextField)super.getTableCellEditorComponent(
table, value, isSelected, row, column);
ftf.setValue(value);
return ftf;
}
//Override to ensure that the value remains an Integer.
public Object getCellEditorValue() {
JFormattedTextField ftf = (JFormattedTextField)getComponent();
Object o = ftf.getValue();

return o;
}
public boolean stopCellEditing() {
JFormattedTextField ftf = (JFormattedTextField)getComponent();
if (ftf.isEditValid()) {
try {

ftf.commitEdit();
} catch (java.text.ParseException exc) { }

return super.stopCellEditing();

}else {return false;
}


}

}
Back to top
bparanj
Guest





PostPosted: Wed May 31, 2006 1:21 am    Post subject: Re: Problem with JTable and DefaultCellEditor Reply with quote

Thank you Steve. I actually got some ideas from the Sun Swing forum.
The following code is based on that:

package swing.table;

import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
import javax.swing.text.JTextComponent;

import client.EditorState;

public class MyTable extends JTable {

public MyTable(TableModel dm) {
super(dm);
}

public Component prepareEditor(TableCellEditor editor, int row, int
col) {
//If the cell is JComboBox then default behaviour is same as
super class.
if(col == 2) {
return super.prepareEditor(editor, row, col);
}

JTextComponent comp = (JTextComponent)
super.prepareEditor(editor, row, col);
//The setText method makes the old value disappear when a user
starts typing in a
// cell
if(!EditorState.getInstance().isRestoreInProgress()) {
comp.setText(null);
}

return comp;
}
}

This table allows the selection of cells in a table. This works fine in
most cases. The problem is that when I select a particular cell in a
table and open another table to display the data, it copies the value
of the old table's cell into the newly opened table cell.

How do I avoid this unwanted copy of old data? Thanks in advance.

BP
http://www.ProblemSolvingSkill.net
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AppletTalk.com Forum Index -> Java GUI Toolkits All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.