So I have a textfield which I want to be max length 10 and only letters, this is what I've came up with:
private void textField1KeyTyped(java.awt.event.KeyEvent evt) {
char c= evt.getKeyChar();
if( !(Character.isAlphabetic(c)) ){
evt.consume();
}
if ((textField1.getText().length()) > 10){
evt.consume();
}
}
It kind of works but I've seen some tutorials that use something like this:
private void textField1KeyTyped(java.awt.event.KeyEvent evt) {
char c= evt.getKeyChar();
if( (Character.isAlphabetic(c)) ){
if((textField1.getText().length()) <= 10){
textField1.setEditable(true);
}else {
textField1.setEditable(false);
}
}else {
if( (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE) ){
textField1.setEditable(true);
}else {
textField1.setEditable(false);
}
}
}
Which one is right?
Both will stop the text-field from consuming further keys.
calling InputEvent.consume() marks the event as consumed, so that the textfield will not consume it and add the key to it's contents.
See What does e.consume() do in java
disabling editing on the textfield with setEditable(false) will also prevent the textfield from editing, that is consuming the key. But it also makes this behaviour, the lock, visible to the user.
I want to globally listen for CTRL + v in SWT. I can successfully listen for CTRL + c but paste seems to be handled differently in SWT. The following Listener shows how it works for copy and how it does not work for paste:
display.addFilter(SWT.KeyDown, new Listener() {
private final int CTRL = SWT.MOD1;
private boolean checkNextEventForPaste = false;
#Override
public void handleEvent(Event event) {
if(event.stateMask == CTRL && event.keyCode == 'c'){
System.out.println("copy: this works!");
}
else if(event.stateMask == CTRL && (event.keyCode == 'v'
|| event.keyCode == 'V'
|| event.keyCode == 0x16
|| event.keyCode == 118)){
System.out.println("paste: does not work!");
}
else if (event.keyCode == CTRL){
//control for paste is fired first
checkNextEventForPaste = true;
}
else if(checkNextEventForPaste){
if(event.keyCode == 65536){
System.out.println("custom solution: seems to not only apply for paste");
}
checkNextEventForPaste = false;
}
}
});
I debugged the paste case and created a custom solution. The paste keyboard short cut creates the following event sequence:
first event with stateMask = 0 and keyCode = CTRL
second event with stateMask = 0 and keyCode = 65536
The problem is that the custom paste solution seems to apply for other shortcuts too. For example the copy shortcut creates the following event sequence:
first event with stateMask = 0 and keyCode = CTRL
second event with stateMask = CTRL and keyCode = 'c'
third event with stateMask = 0 and keyCode = 65536
Why does SWT handle the paste shortcut in a different way? Is it possible that the paste shortcut is already consumed by an other control? Or does anybody know how I can identify the paste shortcut? A VerifyListener is not applicable in my use case. I have implemented a more or less complex UI with custom selection, as you can see here.
The code below works just fine for both Ctrl+c and Ctrl+v
public static void main(String[] args)
{
final Display d = new Display();
Shell s = new Shell(d);
d.addFilter(SWT.KeyDown, e ->
{
if (((e.stateMask & SWT.CTRL) == SWT.CTRL) && (e.keyCode == 'c'))
{
System.out.println("copy");
}
else if (((e.stateMask & SWT.CTRL) == SWT.CTRL) && (e.keyCode == 'v'))
{
System.out.println("paste");
}
});
s.pack();
s.open();
while (!s.isDisposed())
{
if (!d.readAndDispatch())
d.sleep();
}
d.dispose();
}
I have Android soft keyboard which switch between two languages. Each language has it's own layout (xml). The English language is working but Arabic language has bug. When I enter Arabic letters and immediate after pressing number or symbol remove the letters.
private void handleCharacter(int primaryCode, int[] keyCodes) {
if (isInputViewShown()) {
if (mInputView.isShifted()) {
primaryCode = Character.toUpperCase(primaryCode);
}
}
if (isAlphabet(primaryCode) && mPredictionOn) {
mComposing.append((char) primaryCode);
getCurrentInputConnection().setComposingText(mComposing, 1);
updateShiftKeyState(getCurrentInputEditorInfo());
updateCandidates();
}
getCurrentInputConnection().commitText(
String.valueOf((char) primaryCode), 1);
}
#Override public void onFinishInput() {
super.onFinishInput();
// Clear current composing text and candidates.
mComposing.setLength(0);
updateCandidates();
// We only hide the candidates window when finishing input on
// a particular editor, to avoid popping the underlying application
// up and down if the user is entering text into the bottom of
// its window.
setCandidatesViewShown(false);
mCurKeyboard = mQwertyKeyboard;
if (mInputView != null) {
mInputView.closing();
}
}
#Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd,
int candidatesStart, int candidatesEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
candidatesStart, candidatesEnd);
// If the current selection in the text view changes, we should
// clear whatever candidate text we have.
if (mComposing.length() > 0 && (newSelStart != candidatesEnd
|| newSelEnd != candidatesEnd)) {
mComposing.setLength(0);
updateCandidates();
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.finishComposingText();
}
}
}
private void commitTyped(InputConnection inputConnection) {
if (mComposing.length() > 0) {
inputConnection.commitText(mComposing, mComposing.length());
mComposing.setLength(0);
updateCandidates();
}
}
/**
* Helper to update the shift state of our keyboard based on the initial
* editor state.
*/
private void updateShiftKeyState(EditorInfo attr) {
if (attr != null
&& mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
int caps = 0;
EditorInfo ei = getCurrentInputEditorInfo();
if (ei != null && ei.inputType != InputType.TYPE_NULL) {
caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
}
mInputView.setShifted(mCapsLock || caps != 0);
}
}
/**
* Helper to determine if a given character code is alphabetic.
*/
private boolean isAlphabet(int code) {
if (Character.isLetter(code)) {
return true;
} else {
return false;
}
}
Let me know if more code is required. I also checked the related question on stackoverflow regarding this question and it only helped to fix the English language.
The Arabic is RTL, and it works fine when typing English and Arabic, but has problem with numbers and symbols.
I solved the problem by replacing the handlerCharacter method with the following:
private void handleCharacter(int primaryCode, int[] keyCodes) {
if (isInputViewShown()) {
if (mInputView.isShifted()) {
primaryCode = Character.toUpperCase(primaryCode);
}
}
if (isAlphabet(primaryCode) && mPredictionOn) {
mComposing.append((char) primaryCode);
getCurrentInputConnection().setComposingText(mComposing, 1);
updateShiftKeyState(getCurrentInputEditorInfo());
updateCandidates();
}
else {
mComposing.append((char) primaryCode);
getCurrentInputConnection().setComposingText(mComposing, 1);
}
}
I am trying to verify a text in SWT to allow only binary numbers and it works, but my problem is that I have a button that I need to reset the field but it doesn't work.
Here is the code
DACMUX.addVerifyListener(new VerifyListener() {
public void verifyText(VerifyEvent e) {
e.doit = false;
char myChar = e.character;
if (myChar == '1' || myChar == '0' || myChar == '\b'){
e.doit = true;
}
}
});
reset.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
DACMUX.setText("");
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
Interesting case you got there. Took me a while to figure it out.
Right, so here goes: The VerifyListener is fired after you call setText(""). It checks your condition and it validates to false, so nothing changes.
To make it work, you need to add one additional OR case to your if, which checks if Event#text equals "". This is the case when you call setText(""). It won't mess up you other logic.
So here is the working if:
if (myChar == '1' || myChar == '0' || myChar == '\b' || e.text.equals(""))
{
e.doit = true;
}
I've got one textField where I only accept numbers from the keyboard, but now I have to change it as it's a "price textField" and I would also need to accept a dot "." for any kind of prices.
How can I change this in order to get what I need?
ptoMinimoField = new JTextField();
ptoMinimoField.setBounds(348, 177, 167, 20);
contentPanel.add(ptoMinimoField);
ptoMinimoField.setColumns(10);
ptoMinimoField.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char caracter = e.getKeyChar();
if (((caracter < '0') || (caracter > '9'))
&& (caracter != '\b')) {
e.consume();
}
}
});
As suggested by Oracle ,Use Formatted Text Fields
Formatted text fields provide a way for developers to specify the valid set of characters that can be typed in a text field.
amountFormat = NumberFormat.getNumberInstance();
...
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);
I just use a try-catch block:
try {// if is number
Integer.parseInt(String);
} catch (NumberFormatException e) {
// else then do blah
}
JTextField txField = new DoubleJTextField();
Create a file DoubleJTextField.java and be happy
public class DoubleJTextField extends JTextField {
public DoubleJTextField(){
addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char ch = e.getKeyChar();
if (!isNumber(ch) && !isValidSignal(ch) && !validatePoint(ch) && ch != '\b') {
e.consume();
}
}
});
}
private boolean isNumber(char ch){
return ch >= '0' && ch <= '9';
}
private boolean isValidSignal(char ch){
if( (getText() == null || "".equals(getText().trim()) ) && ch == '-'){
return true;
}
return false;
}
private boolean validatePoint(char ch){
if(ch != '.'){
return false;
}
if(getText() == null || "".equals(getText().trim())){
setText("0.");
return false;
}else if("-".equals(getText())){
setText("-0.");
}
return true;
}
}
Don't ever use a KeyListener for this. Your code above has two serious bugs, both caused by the use of a KeyListener. First, it will miss any text that gets pasted in. Whenever I find a field that filters out non-digits, I always try to paste in some text, just for fun. Nine times out of ten, the text gets accepted, because they used a key listener.
Second, you didn't filter out modifiers. If the user tries to save their work by typing control-s while they're in this field, your key listener will consume the event. And if your application assigns, say, a control-5 or alt-5 shortcut to some action, this KeyListener will add a 5 to the field when they type it, even though the user wasn't trying to type a character. You did figure out that you needed to pass the backspace key, but that's not all you need to pass. Your arrow keys won't work. Neither will your function keys. You can fix all these problems, but it starts to be a lot of work.
There's a third disadvantage, but it only shows up if you adapt your application to a foreign alphabet, particularly one that takes multiple keystrokes to generate a single character, like Chinese. These alphabets make KeyListeners useless.
The trouble is this. You need to filter characters, but KeyListeners aren't about characters, they're about keystrokes, which are not the same thing: Not all keystrokes generate characters, and not all characters are generated by keystrokes. You need an approach that looks at characters after they've been generated, and after modified keystrokes have already been filtered out.
The simplest approach is to use a JFormattedTextField, but I've never liked that approach, because it doesn't format or filter as you type. So instead, I will use a DocumentFilter. DocumentFilters don't operate on keystrokes, they operate on the text strings as they get inserted to your JTextField's data model. Hence, all the control-keys, arrow and function keys and such don't even reach the DocumentFilter. All pasted text goes through the DocumentFilter, too. And, for languages that take three keystrokes to generate a single character, the DocumentFilter doesn't get invoked until the character is generated. Here's what it looks like:
ptoMinimoField = new JTextField();
ptoMinimoField.setBounds(348, 177, 167, 20); // Don't do this! See below.
contentPanel.add(ptoMinimoField);
ptoMinimoField.setColumns(10);
PlainDocument document = (PlainDocument) ptoMinimoField.getDocument();
document.setDocumentFilter(new DigitFilter());
}
The DigitFilter class looks like this:
public class DigitFilter extends DocumentFilter {
#Override
public void insertString(FilterBypass fb, int offset, String text,
AttributeSet attr) throws BadLocationException {
super.insertString(fb, offset, revise(text), attr);
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
super.replace(fb, offset, length, revise(text), attrs);
}
private String revise(String text) {
StringBuilder builder = new StringBuilder(text);
int index = 0;
while (index < builder.length()) {
if (accept(builder.charAt(index))) {
index++;
} else {
// Don't increment index here, or you'll skip the next character!
builder.deleteCharAt(index);
}
}
return builder.toString();
}
/**
* Determine if the character should remain in the String. You may
* override this to get any matching criteria you want.
* #param c The character in question
* #return true if it's valid, false if it should be removed.
*/
public boolean accept(final char c) {
return Character.isDigit(c) || c == '.';
}
}
You could write this as an inner class, but I created a separate class so you can override the accept() method to use any criteria you want. You may also notice that I don't test for digits by writing this:
(c < '0') || (c > '9')
Instead, I do this:
Character.isDigit()
This is faster, cleaner, and works with foreign numbering systems. I also don't need your test for the backspace character, '\b'. I'm guessing that your first KeyListener was filtering out the backspace key, which was your first clue that it was the wrong approach.
And on an unrelated note, don't hard code your component positions. Learn how to use the LayoutManagers. They're easy to use, and they'll make your code much easier to maintain.
Have you looked at a JFormattedTextField? It would seem it does what you want.
Enter the double number of JTextField in java
private boolean dot = false;
private void txtMarkKeyTyped(java.awt.event.KeyEvent evt) {
char vChar = evt.getKeyChar();
if (txtMark.getText().equals(""))
dot = false;
if (dot == false){
if (vChar == '.') dot = true;
else if (!(Character.isDigit(vChar)
|| (vChar == KeyEvent.VK_BACK_SPACE)
|| (vChar == KeyEvent.VK_DELETE))) {
evt.consume();
}
} else {
if (!(Character.isDigit(vChar)
|| (vChar == KeyEvent.VK_BACK_SPACE)
|| (vChar == KeyEvent.VK_DELETE))) {
evt.consume();
}
}
}
This bit of code;
if (((caracter < '0') || (caracter > '9'))
&& (caracter != '\b')) {
decides whether to consume the key event. You need to update the condition so it doesn't consume the dot character.
Just right click on TextField / events / key / keytyped
if(!Character.isDigit(evt.getKeyChar())){
evt.consume();}
/////////////
JTextField ptoMinimoField = new JTextField();
ptoMinimoField.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
boolean ret = true;
try {
Double.parseDouble(ptoMinimoField.getText()+e.getKeyChar());
}catch (NumberFormatException ee) {
ret = false;
}
if (!ret) {
e.consume();
}
}
});
maybe can help you for filtering keytyped just number and dot
public void filterHanyaAngkaDot(java.awt.event.KeyEvent evt){
char c = evt.getKeyChar();
if (! ((Character.isDigit(c) ||
(c == KeyEvent.VK_BACK_SPACE) ||
(c == KeyEvent.VK_DELETE))
)&& c==KeyEvent.VK_COMMA
)
{
evt.consume();
}
}
JTextField txtMyTextField = new JTextField();
numOnly(txtMyTextField);
public void numOnly(Object objSource){
((Component) objSource).addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
String filterStr = "0123456789.";
char c = (char)e.getKeyChar();
if(filterStr.indexOf(c)<0){
e.consume();
}
}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {}
});
}
WARNING: This function does not follow proper java documentation
guide.
I have been using this solution, it's simple and efficient:
jtextfield.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char vChar = e.getKeyChar();
if (!(Character.isDigit(vChar)
|| (vChar == KeyEvent.VK_BACK_SPACE)
|| (vChar == KeyEvent.VK_DELETE))) {
e.consume();
}
}
});
private boolean point = false;
private void txtProductCostPriceAddKeyTyped(java.awt.event.KeyEvent evt)
{
char Char = evt.getKeyChar();
if (txtProductCostPriceAdd.getText().equals(""))
point = false;
if (point == false){
if (Char == '.') point = true;
else if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
evt.consume();
}
} else {
if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
evt.consume();
}
}
}
JTextField textField = new JTextField();
textField.setColumns(10);
textField.addKeyListener(new KeyAdapter() {
#Override
public void KeyTyped(KeyEvent e) {
if (!(e.getKeyChar() >= '0' && e.getKeyChar() <= '9')) {
e.consume();
}
}
})
this is the easiest method i have found so far, and it works without any error