Java Key Press Event - java

I am trying to create a Bengali Keyboard using Java Swing. I am accessing key press event and replacing a particular character with relevant Bengali character. The problem I am getting is the original English character is still appending at the end. How to stop it? Here is the code.
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == 54)
{
textField.setText(textField.getText()+(char)2433);
}
if(e.getKeyCode() == 65)
{
textField.setText(textField.getText()+(char)2438);
}
}
The output is coming like "আa", should be only "আ".
Thanks in advance.
Here is the full Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Phonetic extends JFrame
{
public Phonetic()
{
setTitle("Antaryāmī");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(null);
textField = new JTextField();
textField.setFont(new Font("Mukti Narrow", Font.PLAIN, 20));
textField.setBounds(12, 33, 614, 383);
getContentPane().add(textField);
textField.setColumns(10);
textField.addKeyListener(new KeyListener()
{
#Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == 54)
{
textField.setText(textField.getText()+(char)2433);
}
if(e.getKeyCode() == 65)
{
textField.setText(textField.getText()+(char)2438);
}
}
#Override
public void keyTyped(KeyEvent e)
{
}
#Override
public void keyReleased(KeyEvent e)
{
}
});
this.setSize(650, 450);
this.show();
}
/**
*
*/
private static final long serialVersionUID = 1L;
private JTextField textField;
public static void main(String args[])
{
new Phonetic();
}
}

Don't use a KeyListener.
Instead use a DocumentFilter. As text is inserted into the text field the DocumentFilter is invoked. At this time you should translate the typed character to the character that you want to insert into the Document and then invoke the super method. You will need to override both the insertString() and replace() methods.
Read the section from the Swing tutorial on Implementing a Document Filter for more information and an example to get your started.

just use this:
textField.setText((char)2433);
textField.getText()+(char)2433 appends the existing content of the TextField to the new character.
Edit in response to OP's comment:
It's more efficient to translate the user input on an event like a button click. Cause you'll confuse the user if as he/she enters a single letter you convert it to Bengali.
I mean you can wait until the user completes the word, then show the result, and if you need a real time translation (if we can call it so), a better option is to have a separate TextField and there you should say
translateTextField.setText(translateTextField.getText()+(char)2438);
while the event is raised on key press in the original TextField. I hope this is clear.
If you want to edit the code in place, try this: (Suppose convert is a method that converts all the string (s) and the character (e) and concatenate them)
public void keyPressed(KeyEvent e)
{
s = textField.getText();
textField.setText(convert(s, e.getKeyCode));
}

Related

Return to previous control when pressing BACKSPACE

I have looked at many sites and did not get a result. I have some JTextFields that only accept one character. What I need is that when I press BACKSPACE that character is cleared and the focus returns to the previous JTextField and so on. I added a KeyListener to all JTextFields and try KeyTyped, KeyReleased and KeyPressed events but none worked. The code below:
jt.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent evt) {
char c = evt.getKeyChar();
if(Character.isLetter(c) || Character.isISOControl(c))
{
evt = evt;
} else
evt.consume();
}
public void keyReleased(KeyEvent evt) {
if(evt.getKeyChar() == KeyEvent.VK_BACK_SPACE)
{
robot.keyPress(KeyEvent.VK_BACK_SPACE);
robot.keyRelease(KeyEvent.VK_BACK_SPACE);
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}
});
Thanks for any help.
Don't use a KeyListener. Swing was designed to be used with Key Bindings.
Don't use the Robot. The API has a method that allows you to transfer focus.
Here is the basic code for the Key Binding:
textField.getInputMap().put(KeyStroke.getKeyStroke("BACK_SPACE"), "backspace");
textField.getActionMap().put("backspace", new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
c.transferFocusBackward();
}
});
I have some JTextFields that only accept one character.
You may also want to look at Text Field Auto Tab. It is a class that will allow you to automatically tab to the next text field when a character is entered.
I've quickly made a small app that hopefully solved your problem, here's the entire code:
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.GroupLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BackspaceTest extends JFrame implements KeyListener {
// In this example I've used 4 Text Fields, each of which takes 1 character
private JTextField text1, text2, text3, text4;
// I've stored the Text Fields in a ArrayList so we can easily shuffle trough them later
private ArrayList<JTextField> fieldList = new ArrayList<>();
// Numerical value for tracking the currently focused TextField
private int focusIndex;
// This constructor is the first thing that gets called from main
public BackspaceTest() {
init();
}
private void init() {
// Initialize the text fields with 1 character column size
text1 = new JTextField(1);
text2 = new JTextField(1);
text3 = new JTextField(1);
text4 = new JTextField(1);
// Key listeners for implementing 1 character limitations and Backspace functionality
text1.addKeyListener(this);
text2.addKeyListener(this);
text3.addKeyListener(this);
text4.addKeyListener(this);
// The focus listener keeps track of currently focused Text Fields
text1.addFocusListener(new TextFocusListener());
text2.addFocusListener(new TextFocusListener());
text3.addFocusListener(new TextFocusListener());
text4.addFocusListener(new TextFocusListener());
// The default focus is on the first field
text1.requestFocus();
fieldList.add(text1);
fieldList.add(text2);
fieldList.add(text3);
fieldList.add(text4);
// Puts the items on the screen
createLayout(text1, text2, text3, text4);
setTitle("Backspace Test");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
JPanel panel = (JPanel) getContentPane();
GroupLayout gl = new GroupLayout(panel);
panel.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addComponent(arg[1])
.addComponent(arg[2])
.addComponent(arg[3])
);
gl.setVerticalGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addComponent(arg[1])
.addComponent(arg[2])
.addComponent(arg[3])
);
gl.linkSize(text1, text2, text3, text4);
pack();
}
class TextFocusListener implements FocusListener {
#Override
public void focusGained(FocusEvent e) {
focusIndex = fieldList.indexOf(getFocusOwner());
System.out.println(focusIndex);
}
#Override
public void focusLost(FocusEvent e) { }
}
#Override
public void keyTyped(KeyEvent e) { }
#Override
public void keyPressed(KeyEvent e) {
JTextField focusedText = fieldList.get(focusIndex);
// Check if BACKSPACE is pressed and if Text Field is empty and if it's not the first field
if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE &&
focusedText.getText().equals("") &&
focusIndex > 0) {
fieldList.get(--focusIndex).requestFocus();
}
}
#Override
public void keyReleased(KeyEvent e) {
// This limits the amount of characteres to 1. I'm not fully pleased with it but it works for this demonstration
if (text1.getText().length() >= 1)
text1.setText(text1.getText().substring(0, 1));
if (text2.getText().length() >= 1)
text2.setText(text2.getText().substring(0, 1));
if (text3.getText().length() >= 1)
text3.setText(text3.getText().substring(0, 1));
if (text4.getText().length() >= 1)
text4.setText(text4.getText().substring(0, 1));
}
// Here's where the program starts
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new BackspaceTest().setVisible(true);
}
});
}
});
If you don't have time to run it, look at the line 96, I think the Focus Listener is a good way to solve your problem. Hope this helps you out, good luck!

How to substitute a pressed char in Java

When a user presses the "dot" key on the keypad in a in a JTextField I'd like to transparently substitute it with a comma. I tried something like this:
jTextField.addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.VK_DECIMAL) {
event.setKeyChar(',');
}
}
});
but it doesn't work.
Instead of trying to associate a new key with an already happened key event (this is impossible I think), you should try directly manipulating the text of the related JTextField instance via a call like yourTextField.setText(","); in the if statement of your code snippet above.
The sane way of replacing input in a TextField is to use a DocumentFilder on the TextField's Document (http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter).
Thank you all for your answers.
It's true that the better choice would be to write a document filter, but I need to substitute the dot character only if is pressed on the numpad, not when it comes from the regular keyboard.
I know I could set a flag in the keylistener and than read it in the documentfilter, but it sounds a bit too convoluted.
Thank you very much.
Franco
Here is my solution:
public class MyTextField extends JTextField {
private boolean substituteDot;
public MyTextField() {
super();
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent event) {
substituteDot = (event.getKeyCode() == KeyEvent.VK_DECIMAL);
}
#Override
public void keyTyped(KeyEvent event) {
if (substituteDot) {
event.setKeyChar(',');
}
}
});
}
}
Thank you all!
Bye
Franco

Clicking the textfield and clear the text?

Is it possible that when I clicked the textfield it would clear the recent text that was inputed there?. Mine was like, suppose these are textfields.
Name: Last Name First Name Middle Initial
Then I would click the Last Name and it would be cleared, same as First Name and Middle Initial. thanks for reading, hope you can help me.
Consider a FocusListener, one where all the text is selected:
myTextField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fEvt) {
JTextField tField = (JTextField)fEvt.getSource();
tField.selectAll();
}
});
By selecting all of the text, you give the user the option of either typing and thus deleting the current text and replacing it with the new text, or using the mouse or arrow keys to keep the current text and possibly change it.
I think Hovercraft is right. Better to use a FocusListener for this purpose.
I would write a utility class that could deal with this, I've done something similar for auto select. Means I don't have to extend every text component that comes along or mess around with lost of small focus listeners that do the same thing.
public class AutoClearOnFocusManager extends FocusAdapter {
private static final AutoClearOnFocusManager SHARED_INSTANCE = new AutoClearOnFocusManager();
private AutoClearOnFocusManager() {
}
public static AutoClearOnFocusManager getInstance() {
return SHARED_INSTANCE;
}
#Override
public void focusGained(FocusEvent e) {
Component component = e.getComponent();
if (component instanceof JTextComponent) {
((JTextComponent)component).setText(null);
}
}
public static void install(JTextComponent comp) {
comp.addFocusListener(getInstance());
}
public static void uninstall(JTextComponent comp) {
comp.removeFocusListener(getInstance());
}
}
Then you just need to use
JTextField textField = new JTextField("Some text");
AutoClearOnFocusManager.install(textField);
If you're just looking to supply a "prompt" (text inside the field that prompts the user), you could also look at the Prompt API
Why don't use the mouseClicked event?
So, you can have something like
jTextFieldMyText.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTextFieldMyTextMouseClicked(evt);
}
});
private void jTextFieldMyTextMouseClicked(java.awt.event.MouseEvent evt) {
jTextFieldMyText.setText("");
}
In the case of focus
jTextFieldMyText.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
jTextFieldMyTextFocusGained(evt);
}
});
private void jTextFieldMyTextFocusGained(java.awt.event.MouseEvent evt) {
jTextFieldMyText.setText("");
}
If deleting text inmediatelly isn't what's wanted, use selectAll() instead of setText("") as suggested many times

Handle barcode scan in Java

I want to have my application react to barcodes being scanned to trigger button presses. For example the user could scan the ((PRINT)) barcode to activate the print button.
The barcodes will just be treated as if the user had entered some text. I am not sure if the scanners will be set up to append an enter or a tab or nothing on the end, so I don't want to make an assumption on that basis.
The application is a Java/Swing application.
I have looked at keybindings/action maps and the like, but they seem to be focussed on key chords/single key entries. I need it to not trigger the binding until the whole string is entered.
The tricky bit is that this should work wherever the user is focussed in the screen. They will not normally enter ( characters, so some kind of trigger on that might work. I am not sure how to handle the rest of the string though.
Edit: Apologies if it wasn't clear in the question, but the barcode scanner isn't anything "special" to the application, it's just like another keyboard. So the user won't be typing in (print), but effectively that is what the barcode scanner will be doing, if that makes sense.
So there are only two ways to trigger the print: pressing the button, or "typing" the string (print). The tricky part is that the user can be focussed anywhere on the application. I am only worried about if the application has focus as a whole, not which field the user is focussed on. The particular screen in question has checkbuttons and left/right selectors on it, so the user isn't necessarily going to be typing in to a field.
I had a problem just like yours, and created a project (currently proof of concept with some problems) to make barcode handling in swing easier.
It is based in the fact that the barcode readers emulate a keyboard but differently to humans they "type" with a constant timing. It will basically allow you to listen to "barcode read" events.
The project location: https://github.com/hablutzel1/swingbarcodelistener
Demo usage:
public class SimpleTest extends JFrame {
public SimpleTest() throws HeadlessException {
// start of listening for barcode events
Toolkit.getDefaultToolkit().addAWTEventListener(new BarcodeAwareAWTEventListener(new BarcodeCapturedListener() {
#Override
public void barcodeCaptured(String barcode) {
JOptionPane.showMessageDialog(SimpleTest.this, "barcode captured: " + barcode);
}
}), AWTEvent.KEY_EVENT_MASK);
// end of listening for barcode events
getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JLabel("Capture barcode demo"));
getContentPane().add(new JTextField(25));
}
public static void main(String[] args) {
SimpleTest simpleTest = new SimpleTest();
simpleTest.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
simpleTest.setVisible(true);
simpleTest.pack();
}
}
It has some problems now but as a starting point I think it is ok, if you have time to improve it it would be great.
Correct me if I missunderstood, but it sounds like you have a barcode-scanner which will enter text into a field. But you want to be alerted when the text in the field equals something (so an action can take place) regardless of how it was entered (by barcode scanner or key press).
I'd recommend using a DocumentListener to alert you of changes to the text field - this should work with both of your requirements.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TempProject extends Box{
public TempProject(){
super(BoxLayout.Y_AXIS);
final JTextArea ta = new JTextArea();
ta.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void changedUpdate(DocumentEvent arg0) {
doSomething();
}
#Override
public void insertUpdate(DocumentEvent arg0) {
doSomething();
}
#Override
public void removeUpdate(DocumentEvent arg0) {
doSomething();
}
public void doSomething(){
if(ta.getText().equalsIgnoreCase("print")){
System.out.println("Printing...");
//Need to clear text in a separate swing thread
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
ta.setText("");
}});
}
}
});
add(ta);
}
public static void main(String args[])
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setContentPane(new TempProject());
frame.setPreferredSize(new Dimension(500, 400));
frame.pack();
frame.setVisible(true);
}
});
}
}
I do not completely understand the question, and this is a bit too long to put in a comment. As far as I understood it, you have a Swing application and a bar-code scanner which has 3 different ways to trigger the same operation
User enters some text ("print") in the UI and this triggers the print action
The UI has a print button which can be pressed by the user and this triggers the print action
User can scan a "print" bar code and this triggers the print action
The part I do not understand is why the scanning of the bar code, which should trigger the print action, has anything to do with the UI-part where the user can input text.
I assume the scanning of the barcodes happens on another thread then the Event Dispatch Thread. Once you scanned a barcode and parsed it, you need to trigger the "print" action. You can do this directly without bothering going through the UI.
This is my approach. It's working. Just get the miliseconds for ensure doesn't read twice. Just add a Key Listener (implemented in the same JFrame).
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
logger().info("keytyped" + e.getKeyChar() + " code "+e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
logger().info("all keys " + keyspressed);
return;
}
// will not last more than a second...
if (keyspressed == null || System.currentTimeMillis() - currentTimeMillis > 1000) {
keyspressed = e.getKeyChar()+"";
currentTimeMillis = System.currentTimeMillis();
} else {
keyspressed = keyspressed + e.getKeyChar();
currentTimeMillis = System.currentTimeMillis();
}
}
private String keyspressed = null;
private long currentTimeMillis = System.currentTimeMillis();

Removing new line function when enter button is pressed Java

I have a text area that I would like to become blank when the enter button is pressed. I know this would normally be done with a setText method. However when I do this, the text is removed but the new line function created by the return key being pressed. My question is, is the anyway of stopping this default action from happening?
thanks
Are you listening for the ENTER key on the text area and then clearing it? The following works for me:
final JTextArea ta = new JTextArea();
ta.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
ta.setText("");
}
}
#Override
public void keyPressed(KeyEvent e) {
}
});
Hi
I have a text area that I would like to become blank when the enter button is pressed.
This, I understand. Here's how you can do that:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[]args) {
final JFrame frame = new JFrame();
final JTextArea area = new JTextArea();
area.setPreferredSize(new Dimension(200, 200));
area.addKeyListener(new KeyAdapter(){
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
area.setText("");
}
}
});
frame.add(area);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
I know this would normally be done with a setText method. However when I do this, the text is removed but the new line function created by the return key being pressed. My question is, is the anyway of stopping this default action from happening?
That, I don't understand.
The problem is probably that you are not consuming the keystroke event, and although the text area is cleared, the normal processing of the keystroke ends up inserting a newline.
Rather than trapping the keystroke event (which isn't necessarily portable) I would recommend using a DocumentFilter. There is a tutorial here that shows you how to write one. Implement the filter so that when there is a 'newline' in the insert or replace string, replace the entire contents of the document with "".
However this approach can't tell the difference between a newline typed at the keyboard and one pasted into the text area.
Before you clear the text you need to remove the new line code the return button left. You do that with the consume() method.
So to clear your text:
yourkeyevent.consume();
yourTextObject.setText("");
Instead, you can also use:
yourTextarea.setText(null);
yourTextarea.setCaretPosition(-1);
I solved your problem overriding the code in the method "public void keyTyped(KeyEvent e)" instead of "public void keyPressed(KeyEvent e)" and it works.
Here the code:
package versione1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class WhiteEnter {
final JFrame frame = new JFrame();
private JTextArea area = new JTextArea();
public static void main(String[]args) {
WhiteEnter prova = new WhiteEnter();
prova.run();
}
public void run(){
area.setPreferredSize(new Dimension(200, 200));
area.addKeyListener(new PressEnterKeyListener());
frame.add(area);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public class PressEnterKeyListener implements KeyListener{
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == (KeyEvent.VK_ENTER)){
try{
area.setText(null);
area.setCaretPosition(0);
} catch(Exception ex){
ex.printStackTrace();
}
}
}
}
}

Categories

Resources