Enforcing limited character range for jtextfield code not working - java

I am trying to use KeyEvent to limit the characters in a jTextField that it can take as input on the KeyTyped event using the following code:
private void userIDFieldKeyTyped(java.awt.event.KeyEvent evt) {
char c = evt.getKeyChar();
if(c!=KeyEvent.VK_BACK_SPACE && c!=KeyEvent.VK_DELETE){
if (Character.isLetter(c) && Character.isDigit(c)){
} else {
evt.consume();
}
}
}
But the above code is not working as expected, it do not take any character as input, as it is clear from the code I am trying to input only AlphaNumeric characters, is there any way to remove this problem? Also I have tried using KeyEvent.VK_ALPHANUMERIC but it didn't work either.
Edit:
What I mean by limiting the characters is that the text field can take input only certain characters which I have allowed and not that to stop takinginput after a certain number of characters has been alread been entered.

I think that JFormattedTextField handles all your requirements. It can limit the number of characters entered, as well as filter out non-required characters. Here is a small example. The MaskFormatter is responsible for handling the required limitations.
import java.awt.EventQueue;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import javax.swing.text.MaskFormatter;
/**
* For testing class {#code javax.swing.JFormattedTextField}
*/
public class FmTxtFld implements Runnable {
private JFrame frame;
private JFormattedTextField fmtTxtFld;
#Override // java.lang.Runnable
public void run() {
try {
showGui();
}
catch (ParseException xParse) {
xParse.printStackTrace();
}
}
private void showGui() throws ParseException {
frame = new JFrame("FmTxtFld");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Ten alphanumeric characters, i.e. letter or digit.
MaskFormatter formatter = new MaskFormatter("AAAAAAAAAA"); //throws java.text.ParseException
fmtTxtFld = new JFormattedTextField(formatter);
fmtTxtFld.setColumns(10);
JLabel label = new JLabel("JFormattedTextField");
JPanel panel = new JPanel();
panel.add(label);
panel.add(fmtTxtFld);
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
FmTxtFld instance = new FmTxtFld();
EventQueue.invokeLater(instance);
}
}
If you run the above code you will see that the text field only echoes valid characters, i.e. only letters and digits, and will also not accept more that 10 characters.

Related

How to set language in text area in Swing? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need to change the default language into Hebrew in all the text areas in the app. I tried to use Set Local, but it didn't work.
Any idea?
The below code demonstrates the only way I know of to configure a JTextComponent (which JTextArea is a subclass of) so that when it gains input focus it displays Hebrew characters. In other words no need for the user to explicitly change the language after the JTextComponent has gained focus and before the user starts entering text.
import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.im.InputContext;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
public class DfltHbrw implements ActionListener, FocusListener, Runnable {
private static final Locale HEBREW = new Locale("iw", "IL");
private static final String EXIT = "\u05E1\u05D2\u05D5\u05E8";
private JFrame frame;
private JTextArea textArea;
#Override // java.awt.event.ActionEvent
public void actionPerformed(ActionEvent event) {
String actionCommand = event.getActionCommand();
if (EXIT.equals(actionCommand)) {
System.exit(0);
}
}
#Override // java.awt.event.FocusListener
public void focusGained(FocusEvent event) {
InputContext ic = textArea.getInputContext();
ic.selectInputMethod(HEBREW);
}
#Override // java.awt.event.FocusListener
public void focusLost(FocusEvent event) {
// Do nothing.
}
#Override // java.lang.Runnable
public void run() {
showGui();
}
private JPanel createButtons() {
JPanel buttonsPanel = new JPanel();
JButton button = new JButton(EXIT);
button.addActionListener(this);
buttonsPanel.add(button);
return buttonsPanel;
}
private JScrollPane createTextArea() {
textArea = new JTextArea(20, 60);
textArea.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
textArea.addFocusListener(this);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
return scrollPane;
}
private void showGui() {
frame = new JFrame("Hebrew");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createTextArea(), BorderLayout.CENTER);
frame.add(createButtons(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/**
* Start here.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new DfltHbrw());
}
}
I only added the JButton so that there would be more than one [GUI] component so as to allow transferring focus from one component to another.
The relevant part of the above code is the focusGained() method. I added a focus listener to the JTextArea which calls that method when the JTextArea gains focus. In fact the focusGained() method does the actual work of configuring the JTextArea for displaying Hebrew when the user starts to enter text into it.
Note that the same focusGained() method can be used to configure the JTextArea to display any [supported] language. All you need to change is the Locale argument that is passed to the selectInputMethod() method.
Also note that I only set the ComponentOrientation so that the Hebrew text in the JTextArea would look "natural". It is not required in order to configure the JTextArea for displaying Hebrew.

Verifying JTable Input Gets Double Error Message

I am trying to write a TableCellEditor that verifies the input for a JTable cell. I have it working except that the error message is being displayed twice. Here is my tester class:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class Tester {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setPreferredSize(new Dimension(500,100));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model=new DefaultTableModel(null,new String[] {"Col 1","Col 2"});
JTable table=new JTable(model);
table.getColumnModel().getColumn(0).setCellEditor(new decimalCellEditor());
model.insertRow(0,new Object[] {null,null});
JScrollPane scroller=new JScrollPane(table);
frame.add(scroller);
frame.setVisible(true);
frame.pack();
}
}
This is the editor:
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;
public class DecimalCellEditor extends AbstractCellEditor implements TableCellEditor {
/**
*
*/
private static final long serialVersionUID = 1L;
private JTextField number=null;
public DecimalCellEditor() {
number=new JTextField();
}
#Override
public Object getCellEditorValue() {
String s=number.getText();
if (s.equals("")) {
return(s);
}
double x=0.;
try {
x=Double.parseDouble(s);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null,"Value must be numeric",null, JOptionPane.ERROR_MESSAGE, null);
return("");
}
return(Double.toString(x));
}
#Override
public Component getTableCellEditorComponent(JTable table_, Object value_, boolean isSelected_, int row_, int column_) {
number.setText(String.valueOf(value_));
return(number);
}
#Override
public boolean stopCellEditing() {
String s=(String) getCellEditorValue();
if (s.equals("")) {
return(super.stopCellEditing());
}
try {
Double.parseDouble(s);
} catch (NumberFormatException e) {
fireEditingCanceled();
return(false);
}
return(super.stopCellEditing());
}
}
The objective is to assure the user enters a numeric value or no value at all (""). What is causing the error to be displayed and dismissed twice when it is non-numeric and how can I stop it? TIA.
Implementing camickr's suggestion
Assuming I understood the suggestion, I don't need the editor?
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Tester {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setPreferredSize(new Dimension(500,100));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyTableModel model=new MyTableModel(null,new String[] {"Col 1","Col 2"});
JTable table=new JTable(model);
model.insertRow(0,new Object[] {"",""});
JScrollPane scroller=new JScrollPane(table);
frame.add(scroller);
frame.setVisible(true);
frame.pack();
}
}
Overriding getColumnClass:
import javax.swing.table.DefaultTableModel;
public class MyTableModel extends DefaultTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
public MyTableModel(Object[][] data_,String[] columnNames_) {
super(data_,columnNames_);
}
#Override
public Class<?> getColumnClass(int column_) {
if (column_==0) {
return(Double.class);
}
return(getValueAt(0,column_).getClass());
}
}
I obviously didn't do this right as I get exceptions from an unknown source saying:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Cannot format given Object as a Number
I'm guessing there is a problem with my constructor.
First of all class names should start with an upper case character. You have been given links to the Swing tutorials that provide demo code. I'm sure you have access to the Java API. The API and examples all follow the same convention. Learn by example and follow Java conventions!
The objective is to assure the user enters a numeric value or no value at all ("").
Just override the getColumnClass(...) method of the TableModel to return Double.class for the column and the JTable will use an appropriate editor and renderer.
A red border will be placed around the cell and you won't be able to save the data until you fix the problem.
Cannot format given Object as a Number
Edit:
Take the time to think about the change you just made. Take the time to read the error message. Your change just stated the column should contain Double data. So why are you adding an "empty" String in the first column. How can the renderer convert a String to a Double?
Again, if you read the code in the Java tutorials you will see how numeric data is add to the TableModel. I gave you a link to that tutorial long ago because it contains many basics.

Appending point (".") in JTextArea with rigth to left orientation

I've come across unusual problem in Java (1.7 JRE), and I can't find a solution.
I am using JTextArea to write text in it, in form of decimal number, for example 123.4 with right to left orientation. Every time I enter "." in turns up at the beginning of the text, like this .123 and when I enter next number it shows up like it should 123.4
It happens both when I try entering numbers with keyboard and via JButtons using method I wrote. Here's the part of the code:
String number;
JTextArea textAreaUnos;
.
.
.
number=number+".";
textAreaUnos.setText(number);
I've also tried writing it like this:
textAreaUnos.append(".");
but the result is the same when I type, for example
123
.123
123.4
In left to right orientation, this is not happening.
Has anyone had problem like this before, and have you managed to solve it?
One work around is using JTextPane or JEditorPane. Below is an example of JTextPane.
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
class Demo{
public static void main(String[]args){
SwingUtilities.invokeLater(()->{
JFrame frame=new JFrame("Right-Left");
JTextPane box=new JTextPane();
frame.getContentPane().add(box);
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setAlignment(attr, StyleConstants.ALIGN_RIGHT);
box.setParagraphAttributes(attr, true);
frame.setSize(300,200);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
});
}
}
Indeed when you append with RIGHT_TO_LEFT a string which start o ends with a non digit nor letter the output is wrong (i.e 123. gets converted to .123)
I managed to append it right by checking if character is .isLetterOrDigit and append to Start or End depending on the check. I know it's tricky but it was the only solution i found.
Main:
import java.awt.ComponentOrientation;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Main extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JTextArea t1 = new JTextArea("", 10, 15), t2;
public Main() {
Box b = Box.createHorizontalBox();
b.add(new JScrollPane(t1));
t2 = new JTextArea(10, 15);
t2.setEditable(false);
b.add(new JScrollPane(t2));
add(b);
setSize(425, 200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t2.setComponentOrientation ( ComponentOrientation.RIGHT_TO_LEFT);
t1.addKeyListener ( new KeyListener( )
{
#Override
public void keyTyped ( KeyEvent e )
{
}
#Override
public void keyReleased ( KeyEvent e )
{
char check = (char)e.getKeyCode ( );
if(Character.isLetterOrDigit ( check ) )
{
t2.setText ( t1.getText ( ).substring ( 0 , t1.getText ( ).length ( )-1 ) + check);
}
else
{
t2.setText ( check + t2.getText ( ) );
}
}
#Override
public void keyPressed ( KeyEvent e )
{
}
});
}
public static void main(String args[]) {
new Main();
}
}
Test:

How to check JTextField for an entered number

I’m trying to check the number button that has been pressed in an if statement. I’ve tried to google the question but perhaps I cannot phrase the question well enough.
Here is the code, I read that less code is easier to understand, so I’ve tried to condense my question as much as possible, I hope I haven't condensed it too much.
JButton One = new JButton("1");
One.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textArea.append("1");
}
});
if(textArea.equals("1")){
System.out.println("test");//doesnt print
}
use a variable to store the text:
String theText;
theText = textArea.getText();
then do string comparison:
if(theText.equals("1")) {}
or shorthand:
if(textArea.getText().equals("1")) {}
Also, the if statement should be inside the actionPerformed method otherwise it has already been executed (resulting in FALSE) by the time the button is clicked. Use textArea.append() if you want to append a new "1" to each previous "1" in the text area every time the button is clicked, otherwise use textArea.setText() to just continually overwrite the previous "1" that was set from any previous button click. A working example can be seen here:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
public class Tester {
public static void main(String args[]) {
JButton aButton = new JButton("Button");
JPanel aPanel = new JPanel();
JTextArea aTextArea = new JTextArea();
JFrame aFrame = new JFrame();
aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aFrame.setSize(200, 200);
aPanel.add(aTextArea);
aPanel.add(aButton);
aFrame.add(aPanel);
aFrame.setVisible(true);
aButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
aTextArea.setText("1");
if(aTextArea.getText().equals("1")) {
System.out.println("Test Works");
}
}});
}
}
UPDATE:
If you would like to not only check the contents of the text area when the button is pressed, but whenever text is entered. Kind of the same "idea" to your if-statement being outside of the button action listener. You need to use either a FocusListener or a KeyListener on the text area. A focus listener will execute when you either click in, or click out of the text area. A key listener will execute on various types of key press/release etc. I think what you are looking for is a KeyListener based on your comments. I've provided an example of each, that works with my previous example:
/*
This is probably not the one you want
*/
aTextArea.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
if(aTextArea.getText().equals("1")) {
System.out.println("Test Worls");
}
}});
/*
With this KeyListener
The second someone types "1" in the text area
It compares the strings, and the test works
*/
aTextArea.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
String currentText = aTextArea.getText();
if(currentText.equals("1")) {
JOptionPane.showMessageDialog(null, "Test Works");
}
}
public void keyPressed(KeyEvent e) {
}
});
Try inserting the above code in the example I had previously provided. Remember to comment out the button ActionListener and to import the following:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

Best way to remap input of certain characters/keys to a JTextComponent?

I am working on a JTextPane that works (almost) exactly like the tags input field here on stackoverflow. For that I am converting text to components as soon as a user hits enter, tab or space. Naturally I do not want any of those characters to actually be input to the text pane. I found this solution, SSCCE:
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.StyledDocument;
#SuppressWarnings("serial")
public class TagTextPane extends JTextPane {
public TagTextPane() {
this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag");
this.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "finalizeTag");
this.getInputMap().put(KeyStroke.getKeyStroke("TAB"), "focusNext");
this.getActionMap().put("focusNext", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
finalizeTag();
transferFocus();
}
});
this.getActionMap().put("finalizeTag", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
finalizeTag();
}
});
}
private void finalizeTag() {
StyledDocument doc = (StyledDocument) getDocument();
Element element = doc.getCharacterElement(getCaretPosition() - 1);
int start = element.getStartOffset();
int len = element.getEndOffset() - start;
String tag = "";
try {
tag = this.getDocument().getText(start, len);
} catch (BadLocationException e) {
}
this.setSelectionStart(start);
this.setSelectionEnd(start + len);
JLabel label = new JLabel(tag);
label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
this.insertComponent(label);
}
public static void main(String[] args) {
JFrame frame = new JFrame("TagTextPaneTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TagTextPane tPane = new TagTextPane();
frame.setSize(400, 100);
frame.getContentPane().add(tPane);
frame.setVisible(true);
}
}
Hitting "tab" usually causes a tab character to be inserted and hitting "enter" usually causes a line break to be entered, as well as hitting "space" causes a space to be entered. The weird thing is that my code stops line breaks and tabs from being entered, but still allows spaces to be entered normally, while performing the intended action.
Why does this approach behave differently for those keys?
How can I stop the space from being entered? (Maybe I want to extend this behavior to commas and the like later on.)
How can I optimally control the behavior of certain characters and keystrokes in a JTextComponent? I have seen this, where the suggestion is to use a KeyListener, but I have also seen this, where Rob Camick points out, why a KeyListener should not be used. So should I rather use a DocumentFilter, or is that breaking a butterfly on a wheel?
Is this even the best way to build this kind of tag input field?
this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag");
This is handling the keyPressed event for the space character.
You want to handle the keyTyped event of the space character:
this.getInputMap().put(KeyStroke.getKeyStroke(' '), "finalizeTag");

Categories

Resources