I am making a component in SWT that contains a text field and a list. Whenever text is entered it filters the list. So far everything is working great and I am just trying to add some nice usability features.
What I want to do is listen for any key events in the List field, if it is Enter that is pressed I perform the 'ok' action (already done) but otherwise I want focus to change to the text field and have the key event triggered there. Basically, if the focus is on the List field and the user types something I want it to be automatically typed into the text field.
Responding to the keyPressed or keyReleased event is fine for setting the focus to the text field, but I need to then repeat the keyEvent somehow so that whatever was typed is actually entered. Any ideas?
So this is what I did:
itemList.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.keyCode == '\r' || e.keyCode == SWT.KEYPAD_CR) {
okButtonAction();
} else if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.ARROW_LEFT || e.keyCode == SWT.ARROW_RIGHT) {
super.keyReleased(e);
} else if (e.character > 0) {
filterInput.setFocus();
Event event = new Event();
event.type = SWT.KeyDown;
event.keyCode = e.keyCode;
event.character = e.character;
Display.getCurrent().post(event);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
event.type = SWT.KeyUp;
Display.getCurrent().post(event);
}
}
});
I read that the Display.post method was there for doing automatic GUI testing, but it works for my purpose here, so I will use it unless anyone can give me a good reason why not??
My first idea was that there may be a way to re-fire the key event (or fire a copy of it) to the text field. But that may not yield the desired result, because there are some key events you probably don't want transferred from the list to the text, e.g. pressing the Up and Down arrow keys for navigation within the list.
So you should decide which key events trigger the focus transfer. From your question, I understand that you are implementing a text filter, so you should restrict the transfer to text characters. Once you know the character that was entered, you may append it to the filter text manually (or insert at the cursor position of the text field).
Related
In SWT, we can set the tab oder by using the code below:
composite.setTabList(new Control[]{button1, button3});
Is there any way to change the key traversal from Tab to Enter? My application connect to a bar code reader and it just support Enter key after read the barcode
There is a TraverseListener in SWT that can be used to change the effect of traversal keys.
For example, a traverse listener can be used to focus the next field on Enter like this:
text.addTraverseListener(new TraverseListener() {
#Override
public void keyTraversed(TraverseEvent event) {
if (event.detail == SWT.TRAVERSE_RETURN) {
event.doit = false;
// focus next control
}
}
});
Setting the doit flag of the event to false consumes the event and prevents it from causing the default action - if any. In a multi-line text field, the Enter key may begin a new line unless the event was consumed by a listener.
The SWT List lets both left and up arrow keys to go up the list items and both right and down arrow keys to go down the list items by default. But I want to use left and right arrow keys for another propose. How can I remove the left and right arrow keys listener that is in SWT List by default? And then replace my own. Here is the code I want to use:
Listener listListener = new Listener() {
public void handleEvent(Event e) {
int RowIndex = listData.getSelectionIndex();
if(RowIndex == 0){
if (e.keyCode == SWT.ARROW_RIGHT) { //right arrow
//do something
}else if (e.keyCode == SWT.ARROW_LEFT) { //left arrow
//do something
}
}
}
};
list.addListener(SWT.KeyDown, listListener);
Thank you!
You can suppress the default behavior of key strokes by setting the doit flag to false like this:
if( event.keyCode == SWT.ARROW_RIGHT ) {
// do something
event.doit = false;
}
The default behavior of arrows keys is very likely platform dependant. Windows behaves as you describe, but other platforms might behave differently. Setting the doit flag to false will work in any case, whether the key has a default behavior or not.
I would rather not override platform behavior because your applications will then behave inconsistent with respect to the platforms general usage.
The android soft keyboard is toggled from the context menu via
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
It types text fine, but when the Enter is pressed, the keyboard closes. Nothing is capture in onKeyDown(int keyCode, KeyEvent event)
The layout looks like this.
Extra Info: For those wondering, the keyboard input is being sent over a TCP connection, not into any view within the layout.
Check your xml may be you set maxline=1 or may be give singleLine="true"
Alright so this question got no attention but I'm going to put my solution here in case someone else has this problem.
For some reason Android has decided that after typing text (with no EditText around) the Enter key is now an action button and not a newline key.
I managed to capture input by receiving key presses in dispatchKeyEvent() rather than onKeyPress()
#Override
public boolean dispatchKeyEvent(KeyEvent ke)
{
int unicode = ke.getUnicodeChar();
if (ke.getAction() == 0 && ke.getKeyCode() == KeyEvent.KEYCODE_ENTER) // getAction() returns 1 (up) or 0 (down).
{
// do my work here
return true; // end here (doesn't go to onKeyDown())
} else
return super.dispatchKeyEvent(ke);
}
this event is fired twice on key press so it was important to use getAction() in the if statement. For all other keyboard presses, I used onKeyDown() which is why it was important to return super.dispatchKeyEvent(ke); if it wasn't the Enter key.
I have to shift the cells up/down depending upon the up/down arrow key pressed from the keyboard. I am adding a KeyListener (in fact KeyAdapter) on the JTable to achieve it using the keyPressed() method. Now what's happening is that when I am pressing the alphanumeric keys, then I am able to get the selected row using table.getSelectedRow(), but when I am pressing the arrow keys its giving me "-1" always. That means no row is shown selected. I also tried to set the focus on table but it did not work. The code I am usin is as follows:
private void settingKeys() {
controller.getStandardActionDetailsTableEquates().addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("key pressed!!");
controller.getStandardActionDetailsTableEquates().setRowSelectionAllowed(true);
int selectedRow = controller.getStandardActionDetailsTableEquates().getSelectedRow();
System.out.println("selectedRow : " + selectedRow);
controller.getStandardActionDetailsTableEquates().requestFocusInWindow();
if (e.getKeyCode() == KeyEvent.VK_UP) {
System.out.println("up arrow key pressed");
Component editor = controller.getStandardActionDetailsTableEquates().getEditorComponent();
editor.requestFocusInWindow();
System.out.println("cursor : " + controller.getStandardActionDetailsTableEquates().getCursor());
System.out.println("value : " + controller.getStandardActionDetailsTableEquates().getSelectedRow());
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
System.out.println("down arrow key pressed");
}
}
});
}
I even tried to get the cursor position, but could not get it. Also, the editor found did not worked (shown in code). The "selected row" and "value" values are pining as "-1".
Please provide solution to this.
Don't use a KeyListener; use Key Bindings. JTable has the following default bindings in the WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input map:
VK_UP has the key "Table.selectPreviousRow"
VK_DOWN has the key "Table.selectNextRow".
You can replace the bindings with Action instances that update your TableModel as desired. This example may guide you. A complete listing can be obtained using the key binding utility cited here. Implementations may be found in the table's UI delegate, BasicTableUI, et al. The EditorKit actions, examined here, are also worth a look. Alternatively, consider a custom Comparator in your RowSorter, as shown here.
I have a JTextPane where I want to restrict the user to enter a message with only 200 characters. So, I have a KeyListener which listens for a Keyevent and checks for a KeyEvent. If the message is more than 200 characters, a JOptionPane.showMessageDialog is shown to display a warning to the user. This bit works fine.
The problem is that once the warning is displayed and the users clicks on 'OK' he can only use the Backspace key in the JTextPane. I want the user to be able to use the delete key, the arrow keys, the shift and control keys to be able to select the text to be deleted.
Can anybody suggest a way of achieving this??
// Add Key Listener to Send Field
chatEditorKeyListener = new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
checkKeystroke(e);
}
};
private void checkKeystroke(KeyEvent e)
{
//Check if enter or back space is entered
if( e.getKeyCode() != KeyEvent.VK_BACK_SPACE && e.getKeyCode() != KeyEvent.VK_ENTER )
{
// user is typing, so test the size as we go and report when we hit boundary
String text = messageBox.getText();
if(text.length() > maxMessageSize)
{
showAlertBox();
}
}
else if ( e.getKeyCode() == KeyEvent.VK_ENTER)
{
//User sending the message
e.consume();
String text = messageBox.getText();
if(text.length() > maxMessageSize)
{
showAlertBox();
}
Drag-and-drop. Copy-and-paste. Accessibility input methods. There are many reasons why this approach is not appropriate.
Instead restrict the contents through the Document. Set a DocumentFilter through AbstractDocument.setDocumentFilter so that you do not need to subclass or implement the document.
A pop up is not great for user experience. Be more subtle. Not allowing any more character will do (please don't beep!). Possibly add a countdown as twitter and stackoverflow do.
Read the section from the Swing tutorial on "Text Component Features" which contains a section on "Implementing a Document Filter" that does exactly what you want.
Test if the current size+1 hits the boundary, consume the event and show the message box.
It's important to comsume the event to never actually oversize your text box!