Vaadin TextArea keyboard listener consume event - java

I need a customized TextArea component, where I'd like disable some keys (f.e. backspace and del keys). For this I created a vaadin-archetype-widget artifact, and I created two subclasses (MyTextArea and VMyTextArea), and I overrode the onKeyDown method in class VMyTextArea:
#Override
public void onKeyDown(KeyDownEvent event) {
int kc = event.getNativeKeyCode();
if (kc == KeyCodes.KEY_BACKSPACE || kc == KeyCodes.KEY_DELETE) {
return;
}
super.onKeyDown(event);
}
Unfortunately this solution doesn't solve my problem, the backspace and delete keys work normally. My question how to do this?

The solution:
public class VMyTextArea extends VTextArea {
VMyTextArea() {
super();
addKeyDownHandler(new KeyDownHandler() {
public void onKeyDown(KeyDownEvent event) {
int kc = event.getNativeKeyCode();
if (kc == KeyCodes.KEY_BACKSPACE || kc == KeyCodes.KEY_DELETE) {
event.preventDefault();
}
}
});
}
}

Related

JavaFX checking if Event's KeyCode is a digit key

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.

JavaFX key listener for multiple keys pressed implementation?

I would like to create an event handler that listens for multiple key combinations such as holding Ctrl and C at the same time.
Why doesn't something like if((... == Control) && (... == C)) work?
Here is the code I trying to work with:
textField.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
if ((event.getCode() == KeyCode.CONTROL) && (event.getCode() == KeyCode.C)) {
System.out.println("Control pressed");
}
};
});
You can try this solution, it worked for me!
final KeyCombination keyCombinationShiftC = new KeyCodeCombination(
KeyCode.C, KeyCombination.CONTROL_DOWN);
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (keyCombinationShiftC.match(event)) {
logger.info("CTRL + C Pressed");
}
}
});
One way to tackle this problem is to create a KeyCombination object and set some of its properties to what you see below.
Try the following:
textfield.getScene().getAccelerators().put(new KeyCodeCombination(
KeyCode.C, KeyCombination.CONTROL_ANY), new Runnable() {
#Override public void run() {
//Insert conditions here
textfield.requestFocus();
}
});
This would be of some help. KeyCombination.
final KeyCombination keyComb1=new KeyCodeCombination(KeyCode.C,KeyCombination.CONTROL_DOWN);
https://code.google.com/p/javafx-demos/source/browse/trunk/javafx-demos/src/main/java/com/ezest/javafx/demogallery/KeyCombinationDemo.java?r=27
A bit more concise (avoids new KeyCombination()):
public void handle(KeyEvent event) {
if (event.isControlDown() && (event.getCode() == KeyCode.C)) {
System.out.println("Control+C pressed");
}
};
There are methods of the type KeyEvent.isXXXDown() for the other modifier keys as well.

Flush pending AWT events programmatically

Cross-posted: https://forums.oracle.com/forums/thread.jspa?threadID=2512538&tstart=0
Hello, everybody.
Is there a way to flush pending AWT events programmatically? I would like to be able to use it in a code like this:
if (comp.requestFocusInWindow())
{
// flush pending AWT events...
KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
if (focusManager.getPermanentFocusOwner() == comp)
{
// do something...
}
}
Thank you.
Marcos
PS: I know I can use a FocusListener in comp, but it is not an option in my case.
UPDATE:
The essence of my problem is this: to focus the actual editor componente of a JTable before the key that starts the editing is dispatched to it. So I came out with this solution:
private class TextFieldColumnEditor extends MyCustomTextField
{
// TODO
private static final long serialVersionUID = 1L;
private FocusListener _keyDispatcher;
#Override
protected boolean processKeyBinding(final KeyStroke ks, final KeyEvent e, int condition, boolean pressed)
{
InputMap bindings = getInputMap(condition);
ActionMap actions = getActionMap();
if (bindings != null && actions != null && isEnabled())
{
Object binding = bindings.get(ks);
final Action action = binding == null ? null : actions.get(binding);
if (action != null)
{
if (!isFocusOwner() && requestFocusInWindow())
{
// In case something went wrong last time and the
// listener wasn't unregistered.
removeFocusListener(_keyDispatcher);
_keyDispatcher =
new FocusListener()
{
#Override
public void focusGained(FocusEvent evt)
{
removeFocusListener(this);
SwingUtilities.invokeLater(
new Runnable()
{
#Override
public void run()
{
SwingUtilities.notifyAction(action, ks, e, CampoTextoDadosEditorColuna.this, e.getModifiers());
}
}
);
}
#Override
public void focusLost(FocusEvent e)
{
}
};
addFocusListener(_keyDispatcher);
return true;
}
else
{
return SwingUtilities.notifyAction(action, ks, e, this, e.getModifiers());
}
}
}
return false;
}
The class TextFieldColumnEditor is the componente I use in a custom cell editor. As you can see the solution is not perfect for a lot of reasons:
I had to copy the processKeyBinding code from JComponent and change it.
I don't know if SwingUtilities.notifyAction had success, because it is executed in another block of code and I can't return it from the processKeyBinding method. I assume it had. That's why I needed some kind of synchronous focus handling.
I'm sticking with this solution for the time being. Your comments and suggestions would be appreciated.
Marcos
UPDATE 2
Final (simplified) version, after suggestion by #VGR:
private class CellEditorTextField extends JTextField
{
#Override
protected boolean processKeyBinding(final KeyStroke ks, final KeyEvent e, int condition, boolean pressed)
{
InputMap bindings = getInputMap(condition);
ActionMap actions = getActionMap();
if (bindings != null && actions != null && isEnabled())
{
Object binding = bindings.get(ks);
final Action action = binding == null ? null : actions.get(binding);
if (action != null)
{
if (e.getSource() == YourJTable.this && action.isEnabled() && requestFocusInWindow())
{
SwingUtilities.invokeLater(
new Runnable()
{
#Override
public void run()
{
SwingUtilities.notifyAction(action, ks, e, CellEditorTextField.this, e.getModifiers());
}
}
);
return true;
}
else
{
return SwingUtilities.notifyAction(action, ks, e, this, e.getModifiers());
}
}
}
return false;
}
}
Comments and improvements are appreciated.

In GWT is there a way to create a KeyPressEvent for the entire view instead of a single input element?

Right now I have the following code working:
#UiHandler("usernameTextBox")
void onUsernameTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
#UiHandler("passwordTextBox")
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
void keyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}
I would like the ability to have just one listener for all elements on the view without duplicating an event for each textbox.
The end goal is that if they press enter, regardless of where they are on the page, it should submit the form.
Thanks!
What works, but still requires you to specify it for each widget, but doesn't require duplicate code:
#UiHandler({"usernameTextBox", "passwordTextBox"})
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
Yes jackcrews is correct. Also you can try the following. It may be VerticalPanel, DockLayoutPanel etc....
UiBinder.ui.xml
<gwt:VerticalPanel ui:field="mainPanel">
<gwt:Label>Name</gwt:TextBox>
<gwt:TextBox ui:field="textBox">
</gwt:VerticalPanel>
Main.java
#UiField
VerticalPanel mainPanel;
public Main() {
focushandler();
}
void focusHandler() {
mainPanel.addDomHandler(new Handler(), KeyPressEvent.getType());
}
final class Handler implements KeyPressHandler {
#Override
public void onKeyPress(KeyPressEvent event) {
//Code what you expect
}
}
Actually this has more number of lines. But it is good practice.
Regards,
Gnik
I found out that the g:FocusPanel allows me to capture events for everything inside the panel.
#UiHandler("focusPanel")
void onFocusPanelKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}

Getting input from barcode scanner internally without textbox

I have a barcode scanner and in my java application I have to bring a popup to display all the information associated with the barcode from database when the product is scanned using barcode. I have no textbox on the application I have to handle this part internally. How do I do this ? any suggestion ? I am using swing for UI.
EDIT
Barcode scanner is USB one. If we scan something it will output the result into the textbox which has focus. But I have no textbox working on the page opened. Can i work with some hidden textbox and read the value there ?
Since barcode scanner is just a device which sends keycodes and ENTER after reading of each barcode, I'd use a key listener.
final Frame frame = new Frame();
frame.setVisible(true);
frame.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
// your code is scanned and you can access it using frame.getBarCode()
// now clean the bar code so the next one can be read
frame.setBarCode(new String());
} else {
// some character has been read, append it to your "barcode cache"
frame.setBarCode(frame.getBarCode() + e.getKeyChar());
}
}
});
Since was not able to get input via frame.addKeyListener I have used this utility class which uses KeyboardFocusManager :
public class BarcodeReader {
private static final long THRESHOLD = 100;
private static final int MIN_BARCODE_LENGTH = 8;
public interface BarcodeListener {
void onBarcodeRead(String barcode);
}
private final StringBuffer barcode = new StringBuffer();
private final List<BarcodeListener> listeners = new CopyOnWriteArrayList<BarcodeListener>();
private long lastEventTimeStamp = 0L;
public BarcodeReader() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() != KeyEvent.KEY_RELEASED) {
return false;
}
if (e.getWhen() - lastEventTimeStamp > THRESHOLD) {
barcode.delete(0, barcode.length());
}
lastEventTimeStamp = e.getWhen();
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
if (barcode.length() >= MIN_BARCODE_LENGTH) {
fireBarcode(barcode.toString());
}
barcode.delete(0, barcode.length());
} else {
barcode.append(e.getKeyChar());
}
return false;
}
});
}
protected void fireBarcode(String barcode) {
for (BarcodeListener listener : listeners) {
listener.onBarcodeRead(barcode);
}
}
public void addBarcodeListener(BarcodeListener listener) {
listeners.add(listener);
}
public void removeBarcodeListener(BarcodeListener listener) {
listeners.remove(listener);
}
}
In some way similar to #Cyrusmith solution I have created a 'proof of concept' solution (with several limitations right now, but you are invited to fix them :) ) trying to solve the limitations on the previous solutions in this post:
It support barcode readers that doesn't send the ENTER at the end of barcode string.
If the focus is currently on a swing text component and barcode is captured, the barcode doesn't get to the text component and only to the barcode listener.
See https://stackoverflow.com/a/22084579/320594

Categories

Resources