I am working in a project where I have to get input from user by using a JTable. Here I had created a JTable which will have only numerical values. I validated it on keyTyped and its working fine until I press F2 or click on the cell. When I am doing so, it put a cursor in cell and other characters are also being typed.
jtblValues.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_ENTER && (jtblValues.getRowCount() == (jtblValues.getSelectedRow()+1)))
model.addRow(new Object[]{"", "", ""});
else if (e.getKeyCode()==KeyEvent.VK_TAB && (jtblValues.getRowCount() == (jtblValues.getSelectedRow()+1)) && (jtblValues.getColumnCount() == (jtblValues.getSelectedColumn()+1)))
model.addRow(new Object[]{"", "", ""});
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if (!((c >= '0') && (c <= '9') || (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE) || (c == KeyEvent.VK_ENTER) || (c == KeyEvent.VK_TAB))) {
getToolkit().beep();
e.consume();
}
}
} );
So, how to prevent user by typing other characters than numbers?
Thanks.
You can achieve this by providing an appropriate TableCellEditor as described in Using an Editor to Validate User-Entered Text section of How to Use Tables tutorial.
The key is using a JFormattedTextfield as editor with NumberFormatter and NumberFormat. For instance:
NumberFormat integerFormat = NumberFormat.getIntegerInstance();
NumberFormatter formatter = new NumberFormatter(integerFormat);
formatter.setAllowsInvalid(false);
JFormattedTextField textfield = new JFormattedTextField(formatter);
See How to Use Formatted Text Fields tutorial for further details.
Off-topic
It's preferable use Keybinding over KeyListeners when you're working with Swing for the reasons discussed in this topic: Key bindings vs. key listeners in Java. Refer to the tutorial to start with KeyBinding: How to Use Key Bindings
maybe I have same problem like you. This code worked for me using KeyListener.
//define KeyAdapter variable at header
KeyAdapter key1, key2;
make class TableEditor like this:
final class TableEditor extends DefaultCellEditor{
public TableEditor(){
super(new JTextField());
setClickCountToStart(1);
}
#Override
public Component getTableCellEditorComponent(final JTable table,Object value,boolean isSelected,final int row,final int column){
final JTextField cellEdit = (JTextField) super.getTableCellEditorComponent(table,value,isSelected,row,column);
cellEdit.setText((String)value);
table.setSurrendersFocusOnKeystroke(true);
//remove previous keyListener that store in memory
cellEdit.removeKeyListener(key1);
cellEdit.removeKeyListener(key2);
// KeyAdapter that accept numeric only (key1)
key1 = new KeyAdapter() {
#Override
public void keyPressed(KeyEvent evt){
// just for check how much times Enter keyEvent store in memory
if(evt.getKeyCode()==KeyEvent.VK_ENTER) System.out.println("enter 2");
}
#Override
public void keyReleased(KeyEvent evt){
}
#Override
public void keyTyped(KeyEvent evt){
char c = evt.getKeyChar();
if (!Character.isDigit(c)) evt.consume();
}
};
// KeyAdapter that accept all char (key2)
key2 = new KeyAdapter() {
#Override
public void keyPressed(KeyEvent evt){
// just for check how much times Enter keyEvent store in memory
if(evt.getKeyCode()==KeyEvent.VK_ENTER) System.out.println("enter 2");
}
#Override
public void keyReleased(KeyEvent evt){
}
#Override
public void keyTyped(KeyEvent evt){
}
};
// cell column 3rd accept numeric only > addKeyListener(key1)
if (column == 3) {
cellEdit.addKeyListener(key1);
cellEdit.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
cellEdit.setCaretPosition(1);
return cellEdit;
}
// other cell accept all char > addKeyListener(key2)
else {
cellEdit.addKeyListener(key2);
cellEdit.setHorizontalAlignment(javax.swing.JTextField.LEFT);
return cellEdit;
}
}
}
Then call the class using:
MyTable.setDefaultEditor(Object.class, new TableEditor());
That's all. I hope this code worked for you.
you can do this easy way in netbeans:
Step 1:see image 1 here
Step 2:see image 2 here
Step 3:see image 3 here
Related
I am trying to generate random questions from my String array called Questions. There 10 items inside. I am trying to set the text of JLabel where once the button is click one of the questions from the array will randomly be selected and displayed. However these 2 sections of code doesn't return anyting.
public String getNextQuestion() {
int NextQues = (int)(Math.random()*10);
return Questions[NextQues];}
public void actionPerformed (ActionEvent e) {
if(e.getSource() == Button) {
Hello.setText(Questions[NextQues]);
Don't hardcode the magic number 10 in getNextQuestion(). I would prefer
ThreadLocalRandom over Math.random(). Like,
public String getNextQuestion() {
return Questions[ThreadLocalRandom.current().nextInt(Questions.length)];
}
Then invoke that method in actionPerformed like,
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Button) {
Hello.setText(getNextQuestion());
}
}
You should be calling your method getNextQuestion
OK, you need an actionlistener on your button in order for something to happen. Something like
public String getNextQuestion() {
int NextQues = (int)(Math.random()*10);
return Questions[NextQues];}
// inside main method
...
Button.addActionListener (
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Hello.setText(getNextQuestion());
}
});
...
I'm creating a custom textfield class in which i have a custom behaviour depending on if the user types digit keys on it.
!event.getCode().isDigitKey() always returns true, even when i type digits. I tried to check if KeyCode is a letter also and still it returns false. What seems to be the issue here?
I always get false when checking the event's KeyCode against any other KeyCode, even when they should be equal.
public class ScoreField extends TextField implements Customizable {
public ScoreField() {
super();
customize();
}
#Override
public void customize() {
this.setOnKeyTyped(new EventHandler<KeyEvent>() {
int curChar = 0;
#Override
public void handle(KeyEvent event) {
event.consume();
KeyCode keyTyped = event.getCode();
char charTyped = event.getCharacter().charAt(0);
System.out.println(charTyped);
// Do nothing if not a digit
if (!event.getCode().isDigitKey()) {
System.out.println("NOT A DIGIT KEY");
if (keyTyped == KeyCode.BACK_SPACE) {
System.out.println("RESETTING");
resetText();
return;
}
return;
}
if (getText().length() >= 5) {
if (curChar == 2) {
curChar = 3;
}
if (curChar == 5) {
curChar = 0;
}
StringBuilder builder = new StringBuilder(getText());
builder.setCharAt(curChar, charTyped);
setText(builder.toString());
curChar++;
return;
}
if (getText().length() == 2) {
setText(getText() + ":");
}
setText(getText() + charTyped);
}
});
}
private void resetText() {
setText("");
}
}
As James_D stated:
For key typed events, the code is always KeyCode.UNDEFINED
So i did as he suggested and instead of checking the KeyCode if it's a digit, i checked event.getCharacter()[0] using Character.isDigit(char) in the 1ST if statement, and it worked perfectly for my case.
P.S: I tried to use a TextFormatter with a StringConverter, but i couldn't get it to work.
How can I detect the Windows key modifier for KeyEvent? I have add the code:
textField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if ((e.getKeyCode() & KeyEvent.VK_ESCAPE) == KeyEvent.VK_ESCAPE) {
textField.setText("");
}
}
});
But the problem is, when I use the Windows zoom and try to exit from it using Win + Escape, if focus is in TextField, its content clears. I've tried filter by e.getModifiersEx(), but it returns 0. The only way I've found is to detect whether Windows pressed or not, is to create boolean field and change it's value when Windows pressed/released.
So, is there any way to get the Windows key pressure state from KeyEvent for ESCAPE released event?
The way I used for myself:
AbstractAction escapeAction = AbstractAction() {
public void actionPerfomed(ActionEvent e) {
setText("");
}
}
textField.addCaretListener(new CaretListener() {
#Override
public void caretUpdate(CaretEvent e) {
if (textField.getText() == null || textField.getText().isEmpty()) {
textField.getActionMap().remove("escape");
textField.getInputMap().remove(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
} else {
textField.getActionMap().put("escape", escapeAction);
textField.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), escapeAction);
}
}
});
I'm having some trouble using two comboboxes to affect the state of one item. Each combo box has a value between 1 and 99, I'm trying to change the values in each, combine them, then display this value on a jlabel. So far I can only the first combobox seems to impact the formula. I have simplified it to the following and thanks for any help :)
private int value1int, value2int;
value1.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent ex)
{
if (ex.getStateChange() == ItemEvent.SELECTED)
{
// assume single selection
int value1int = (Integer)ex.getItemSelectable().getSelectedObjects()[0];
}
}
});
value2.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent exs)
{
if (exs.getStateChange() == ItemEvent.SELECTED)
{
// assume single selection
int value2int = (Integer)exs.getItemSelectable().getSelectedObjects()[0];
}
}
});
overallValue2.setText((Integer.toString(value1int + value2int)));
overallValue2.revalidate();
you have to do something like that:
public class GUI extends JFrame ...
private int labelVal;
...
// combobox events - The same code to both comboboxes must works
public void itemStateChanged(ItemEvent exs)
{
if (exs.getStateChange() == ItemEvent.SELECTED)
{
// assume single selection
int aux = (Integer)combobox1.getSelectedItem()+(Integer)combobox2.getSelectedItem();
int labelVal= aux;
}
}
Them refresh the screen
I have the ListSelectionListener which tells me when the cell is selected with the mouse.
JGrid grid = new JGrid();
grid.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
grid.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(final ListSelectionEvent e) {
e.getFirstIndex();
e.getLastIndex()
}
}
I want to select the sell only when the button shift is hold. How can i do it?
I need it for the multiple selection. When the user holds shift and clicks the cells it gives me getFirstIndex() and getLastIndex().
Add a KeyListener similar to this to your JGrid, assuming JGrids takes keyListeners
boolean shiftIsDown = false;
yourJGrid.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode == e.VK_SHIFT) shiftIsDown = true;
}
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode == e.VK_SHIFT &&
shiftIsDown == true) shiftIsDown = false;
}
public void keyTyped(KeyEvent e)
{
// nothing
}
});
Now when you get a valueChanged() event, just check to see if your boolean "shiftIsDown" value is true, and if so you can do your selection.