Robot class java , typing a string issue - java

I m using the following loop , but its only typing the first charecter and the rest as numbers, any idea ?
import java.awt.*;
import javax.swing.KeyStroke;
public class test {
public static void main(String[] args) throws AWTException
{
Robot r = new Robot();
String s = "Face";
for (int i = 0; i < s.length(); i++)
{
char res = s.charAt(i);
r.keyPress(res);
r.keyRelease(res);
r.delay(1000);
}
}
}
OUTPUT typing : F135

The keyPress/Release methods need an int value that represents the character you want to type. These value are the key code for each character as determined by the KeyEvent.VK_??? variables.
Try:
import java.awt.*;
import java.util.*;
import java.lang.reflect.Field;
import java.awt.event.*;
import javax.swing.*;
public class RobotCharacter
{
public static void main(String[] args)
throws Exception
{
JTextField textField = new JTextField(10);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( textField );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
Robot robot = new Robot();
typeCharacter(robot, "a");
typeCharacter(robot, "b");
typeCharacter(robot, "C");
typeCharacter(robot, "D");
}
public static void typeCharacter(Robot robot, String letter)
{
try
{
boolean upperCase = Character.isUpperCase( letter.charAt(0) );
String variableName = "VK_" + letter.toUpperCase();
Class clazz = KeyEvent.class;
Field field = clazz.getField( variableName );
int keyCode = field.getInt(null);
robot.delay(1000);
if (upperCase) robot.keyPress( KeyEvent.VK_SHIFT );
robot.keyPress( keyCode );
robot.keyRelease( keyCode );
if (upperCase) robot.keyRelease( KeyEvent.VK_SHIFT );
}
catch(Exception e)
{
System.out.println(e);
}
}
}
However, even this won't work for all characters. For example on my keyboard the "%" is above the "5". You can't use VK_PERCENT. The key stroke needed is VK_5 along with a shift. There is no way to know the actual mapping of your keyboard to do this automatically.
So a Robot is not a good way to do this.

The Robot class uses key codes which are defined here: http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/event/KeyEvent.html, not raw characters. You need to call it like this:
r.keyPress(KeyEvent.VK_A);
r.keyRelease(KeyEvent.VK_A);

# camickr I made a small edit to your scipt to accomodate a string rather than a letter . Please find below . It helped me Thanks :) function call : typeCharacter(robot, "thanks");
public static void typeCharacter(Robot robot, String letter)
{
for(int i=0;i<letter.length();i++){
try
{
boolean upperCase = Character.isUpperCase( letter.charAt(i) );
String KeyVal=Character.toString(letter.charAt(i));
String variableName = "VK_" + KeyVal.toUpperCase();
Class clazz = KeyEvent.class;
Field field = clazz.getField( variableName );
int keyCode = field.getInt(null);
robot.delay(1000);
if (upperCase) robot.keyPress( KeyEvent.VK_SHIFT );
robot.keyPress( keyCode );
robot.keyRelease( keyCode );
if (upperCase) robot.keyRelease( KeyEvent.VK_SHIFT );
}
catch(Exception e)
{
System.out.println(e);
}
}
}

You could also load your String to the clipboard and just paste it where ever you want to.
StringSelection selection = new StringSelection("Hello World");
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
robo.keyPress(KeyEvent.VK_CONTROL);
robo.keyPress(KeyEvent.VK_V);
robo.keyRelease(KeyEvent.VK_V);
robo.keyRelease(KeyEvent.VK_CONTROL);

You can make your life easy if you create a function receiving a string to be typed:
public void keyboardString(final String text) {
if (text != null) {
try {
final Robot robot = new Robot();
for (int i = 0; i < text.length(); i++) {
final char ch = text.charAt(i);
final boolean upperCase = Character.isUpperCase(ch);
final int keyCode = KeyEvent.getExtendedKeyCodeForChar(ch);
robot.delay(10);
if (upperCase) {
robot.keyPress(KeyEvent.VK_SHIFT);
}
robot.keyPress(keyCode);
robot.keyRelease(keyCode);
if (upperCase) {
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}
} catch (final Exception e) {
System.out.println(e);
}
}
}

Related

How to account for input errors in calculator program?

I'm writing a calculator program for my java class. I want to account for errors like
User decides to divide by 0. I want the calculator to be able to acknowledge this error and display ERROR.
The user enters 6+7+ and then hits the equal button.
I want, once again, for the calculator to acknowledge that there is an error. I was hoping I could get some hints as to how to go about this. Thanks!
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Calculator
{
JFrame window;
// stuff for top panel
JPanel topPanel;
JTextField expr,result;
JButton equals;
// stuff for bottom panel
JPanel bottomPanel,digitsPanel,opsPanel;
JButton[] digits,ops;
JButton clear, clearEntry;
Container content;
Listener listener;
String[] oplabels = { "+", "-", "/", "*" };
public Calculator()
{
listener = new Listener(); // our Listener class implements ActionListener
window= new JFrame("GUI Calc");
content=window.getContentPane();
content.setLayout( new GridLayout(2,1) );
topPanel=new JPanel();
topPanel.setLayout( new GridLayout(1,3) );
// TOP PANEL WORK
expr = new JTextField( );
equals = new JButton("=");
equals.addActionListener( listener );
result = new JTextField( );
topPanel.add( expr );
topPanel.add( equals );
topPanel.add( result );
// BOTTOM PANEL WORK
bottomPanel = new JPanel();
bottomPanel.setLayout( new GridLayout(1,2) );
digitsPanel = new JPanel();
digitsPanel.setLayout( new GridLayout(4,3) );
opsPanel = new JPanel();
opsPanel.setLayout( new GridLayout(4,1) );
digits = new JButton[12];
ops = new JButton[4];
for (int i=0 ; i<10 ; i++)
{
digits[i] = new JButton( i+"" );
digits[i].addActionListener(listener);
digitsPanel.add( digits[i] );
}
clear = new JButton( "C" );
clearEntry = new JButton( "CE" );
clear.addActionListener(listener);
clearEntry.addActionListener(listener);
digitsPanel.add( clear );
digitsPanel.add( clearEntry);
for (int i=0 ; i<4 ; i++)
{
ops[i] = new JButton( oplabels[i] ) ;
ops[i].addActionListener(listener);
opsPanel.add( ops[i] );
}
bottomPanel.add( digitsPanel );
bottomPanel.add( opsPanel );
content.add( topPanel);
content.add( bottomPanel);
window.setVisible(true);
}
class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Component clicked = (Component) e.getSource();
if ( clicked == equals )
{
result.setText( evaluate( expr.getText() ) );
return;
}
for ( int i=0 ; i<10 ; i++)
{
if ( clicked == digits[i] )
{
expr.setText( expr.getText() + i );
return;
}
}
if ( clicked == clear )
{
expr.setText("0");
return;
// do something
}
/* if (clicked == clearEntry)
{
expr.setText(expr.getDigits[i]);
}
for (int i=0; i < 10; i++)
{
if (clicked == digits[i])
{
int lastValue = clicked;
if(clicked == clearEntry)
{
expr.setText(expr.getText()-clicked);
return;
}
}
} */
for ( int i=0 ; i<4 ; i++ )
{
if(clicked == digits[i])
{
expr.setText(expr.getText() + oplabels[i]);
return;
}
// tack on that operator to the expr string
}
}
String evaluate( String exp )
{
return "NOT WRITTEN YET";
}
}
public static void main(String [] args)
{
new Calculator();
}
}
I'm still working on it. Especially where I'm trying to figure out the clearEntry button so I have put that section as a comment because its still a work in progress.
You can try this:
add a new class(Calculator) member:
Component last_clicked;
Inside Constructor:
last_clicked=null;
Before every return statement of actionPerformed, you can add this:
last_clicked=clicked;
Now, in actionPerformed method, when checking value of clicked, you can do this:
When clicked is '0' & last_clicked is '/', you can display error 1.
When clicked is 'equals' & last_clicked is an operator, you can display error 2.

Can someone help me work out the kinks in my program? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have to write a calculator program using the Gui components. I have written the program but I'm having issues with my CE button. It is giving me errors. I'm also getting and error in my for loop where I add the operand labels to the expression. I was just hoping to get some help in fixing these errors. Thank you! Please ignore the comments. They are there for my to keep track of what I have to do.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Calculator
{
JFrame window;
// stuff for top panel
JPanel topPanel;
JTextField expr,result;
JButton equals;
// stuff for bottom panel
JPanel bottomPanel,digitsPanel,opsPanel;
JButton[] digits,ops;
JButton clear, clearEntry;
Container content;
Listener listener;
String[] oplabels = { "+", "-", "/", "*" };
public Calculator()
{
listener = new Listener(); // our Listener class implements ActionListener
window= new JFrame("GUI Calc");
content=window.getContentPane();
content.setLayout( new GridLayout(2,1) );
topPanel=new JPanel();
topPanel.setLayout( new GridLayout(1,3) );
// TOP PANEL WORK
expr = new JTextField( );
equals = new JButton("=");
equals.addActionListener( listener );
result = new JTextField( );
topPanel.add( expr );
topPanel.add( equals );
topPanel.add( result );
// BOTTOM PANEL WORK
bottomPanel = new JPanel();
bottomPanel.setLayout( new GridLayout(1,2) );
digitsPanel = new JPanel();
digitsPanel.setLayout( new GridLayout(4,3) );
opsPanel = new JPanel();
opsPanel.setLayout( new GridLayout(4,1) );
digits = new JButton[12];
ops = new JButton[4];
for (int i=0 ; i<10 ; i++)
{
digits[i] = new JButton( i+"" );
digits[i].addActionListener(listener);
digitsPanel.add( digits[i] );
}
clear = new JButton( "C" );
clearEntry = new JButton( "CE" );
clear.addActionListener(listener);
clearEntry.addActionListener(listener);
digitsPanel.add( clear );
digitsPanel.add( clearEntry);
for (int i=0 ; i<4 ; i++)
{
ops[i] = new JButton( oplabels[i] ) ;
ops[i].addActionListener(listener);
opsPanel.add( ops[i] );
}
bottomPanel.add( digitsPanel );
bottomPanel.add( opsPanel );
content.add( topPanel);
content.add( bottomPanel);
window.setVisible(true);
}
class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Component clicked = (Component) e.getSource();
if ( clicked == equals )
{
result.setText( evaluate( expr.getText() ) );
return;
}
for ( int i=0 ; i<10 ; i++)
{
if ( clicked == digits[i] )
{
expr.setText( expr.getText() + i );
return;
}
}
if ( clicked == clear )
{
expr.setText("0");
return;
// do something
}
for (int i=0; i < 10; i++)
{
if (clicked == digits[i])
{
int lastValue = i;
return;
}
}
if ( clicked == clearEntry )
{
expr.setText(expr.getText() - lastValue);
return;
// do something
}
for ( int i=0 ; i<4 ; i++ )
{
if(clicked == oplabels[i])
{
expr.setText(expr.getText + oplabels[i]);
return;
}
// tack on that operator to the expr string
}
}
String evaluate( String exp )
{
return "NOT WRITTEN YET";
}
}
public static void main(String [] args)
{
new Calculator();
}
}
Problem #1
The compiler is complaining about expr.setText(expr.getText() - lastValue); because lastValue is undefined.
Having a close look at the code, the only place that lastValue is defined is within the for-loop before the if statement...but the next issues thereturn` statement following it's decleration...
for (int i = 0; i < 10; i++) {
if (clicked == digits[i]) {
int lastValue = i;
return;
}
}
if (clicked == clearEntry) {
expr.setText(expr.getText() - lastValue);
return;
// do something
}
This not only makes the lastValue useless, but it's unlikely that the if statement would ever be reached...
Problem #2
for (int i = 0; i < 4; i++) {
if (clicked == oplabels[i]) {
expr.setText(expr.getText + oplabels[i]);
return;
}
// tack on that operator to the expr string
}
clicked is defined as Component clicked = (Component) e.getSource(); and oplables are defined as String[] oplabels = {"+", "-", "/", "*"};. String and Component are not comparable (also, you want expr.getText() not expr.getText).
I think you want to do something more like...
if (clicked instanceof JButton) {
JButton btn = (JButton)clicked)
for (int i = 0; i < oplabels.length; i++) {
if (oplabels[i].equals(btn.getText()) {
//...
}
}
}
Line 128: clicked is a Component and oplabels[i] is a string - you can't compare them directly.
Line 130: Missing () on getText() call.

show warning if users enter letter instead number in java applet

I am writing an tip calculator app in java applet with GUI, my question is how I make sure the error message will pop up if users enter letter instead of number
it is my first time asking question, please be easy on me! Thanks!!!
import objectdraw.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// Typing in the text field and hitting return adds text to text area.
// Clicking on button erases the text area.
public class TextApplet extends Controller implements ActionListener
{
private static final int ROWS = 1; // rows in TextArea
private static final int COLS = 10; // cols in text field & area
private String amount;
private float number;
private JTextField inField, output; // Input field
private JButton clear, calc;
// button to clear output
public void begin()
{
Container contentPane = getContentPane();
JPanel topPanel = new JPanel(); // prepare text field & label
JLabel inLabel = new JLabel("Bill Cost: ");
inField = new JTextField(COLS);
inField.addActionListener(this);
JLabel topTitle = new JLabel("Tip Calculator", JLabel.CENTER);
JPanel combinePanel = new JPanel();
combinePanel.add ( inLabel );
combinePanel.add ( inField );
JPanel combinePanel1 = new JPanel();
combinePanel1.add ( topTitle );
topPanel.add ( combinePanel1 );
topPanel.add ( combinePanel );
topPanel.setLayout ( new GridLayout ( 3,1) );
contentPane.add(topPanel,BorderLayout.NORTH);
JPanel centerPanel = new JPanel(); // prepare text area & label
JLabel outLabel = new JLabel("Bill + Tip:");
output = new JTextField(COLS);
output.setEditable(false); // Prevent user from wrting in output
centerPanel.add(outLabel);
centerPanel.add(output);
contentPane.add(centerPanel,BorderLayout.CENTER);
JPanel bottomPanel = new JPanel();
// create button
clear = new JButton(" Clear ");
calc = new JButton("Calculate");
calc.addActionListener(this);
clear.addActionListener(this);
bottomPanel.add(calc);
bottomPanel.add(clear);
contentPane.add(bottomPanel,BorderLayout.SOUTH);
validate();
}
// add text to area if user hits return, else erase text area
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == calc )
{
amount = inField.getText();
number = ( Float.parseFloat( amount ) );
number = (15*number/100);
output.setText ( Float.toString ( number ) + '$' );
}
else if (evt.getSource() == clear )
{
output.setText("$");
inField.setText("");
}
}
}
There are any number of ways you might achieve this, you could use
An InputVerifier
A JFormattedTextField
A JSpinner
Or a DocumentFilter and examples
Take a look at javax.swing.InputVerifier. That can be easily attached to a JTextField
JTextField inputField = new JTextField();
inputField.setInputVerifier(new NumericInputVerifier());
private class NumericInputVerifier extends InputVerifier
{
#Override
public boolean verify(JComponent input)
{
if (((JTextField) input).getText().matches("[0-9]+"))
{
return true;
}
else
{
JOptionPane.showMessageDialog(input, "Only numbers are allowed", "Warning", JOptionPane.WARNING_MESSAGE);
return false;
}
}
}
A complete example can be found here.
Edit Added an example of how to use InputVerifier to limit to numeric input. You'll want to double check the regex, but the basic idea is there...
Use a JFormattedTextField or a DocumentFilter. Then the user won't even be able to enter a non-numeric digit. See:
How to Use Formatted Text Fields
Implementing a Document Filter
For the document filter you will need to check each chraacter as it is entered to make sure it is a digit.
It is always better to do simple edits like that as the user types, rather than wait until you click on a button to do processing.
Hello Friend I will give a suggestion
please add validation when call actionPerformed method
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == calc )
{
if(validate()){
amount = inField.getText();
number = ( Float.parseFloat( amount ) );
number = (15*number/100);
output.setText ( Float.toString ( number ) + '$' );
}
else{
// show message for inter valid number or any other
}
}
else if (evt.getSource() == clear )
{
output.setText("$");
inField.setText("");
}
}
boolean validate(){
try{
amount = inField.getText();
number = ( Float.parseFloat( amount ) );
return true;
}
catch(Exception e){
return false;
}
}
If you try to call Float.parseFloat on a String that cannot be converted to a float, it will throw a NumberFormatException. You need to catch this exception.
try {
number = ( Float.parseFloat( amount ) );
number = (15*number/100);
output.setText ( Float.toString ( number ) + '$' );
} catch(NumberFormatException e) {
//code to show error message here
}
Well considering, you'd have to turn the string into an integer to do the math, you could do this:
try {
int number = Ineger.parseInt(inField.getText());
} catch (NumberFormatException e) {
//SHOW WARNING
}
if (Label1.getText().matches("[0-9]+"))
// does Label1 containts numbers.
{
// do math
}
else
{
// warning
Lavbel1.setText("");
}

how to validate a jtextfield to accept only integer numbers [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Restricting JTextField input to Integers
Detecting JTextField “deselect” event
i need to validate a JTextField by allowing the user to input only integer values in it if user enters any char other than numbers a JOptionPane.show messagebox should appear showing that the value entered are incorrect and only integer numbers are allowed. I have coded it for a digit values but i also need to discard the alphabets
public void keyPressed(KeyEvent EVT) {
String value = text.getText();
int l = value.length();
if (EVT.getKeyChar() >= '0' && EVT.getKeyChar() <= '9') {
text.setEditable(true);
label.setText("");
} else {
text.setEditable(false);
label.setText("* Enter only numeric digits(0-9)");
}
}
Instead of using a JFormattedTextField, you may write a custom JTextField with a document that allows only integers. I like formatted fields only for more complex masks...
Take a look.
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
/**
* A JTextField that accepts only integers.
*
* #author David Buzatto
*/
public class IntegerField extends JTextField {
public IntegerField() {
super();
}
public IntegerField( int cols ) {
super( cols );
}
#Override
protected Document createDefaultModel() {
return new UpperCaseDocument();
}
static class UpperCaseDocument extends PlainDocument {
#Override
public void insertString( int offs, String str, AttributeSet a )
throws BadLocationException {
if ( str == null ) {
return;
}
char[] chars = str.toCharArray();
boolean ok = true;
for ( int i = 0; i < chars.length; i++ ) {
try {
Integer.parseInt( String.valueOf( chars[i] ) );
} catch ( NumberFormatException exc ) {
ok = false;
break;
}
}
if ( ok )
super.insertString( offs, new String( chars ), a );
}
}
}
If you are using NetBeans to build your GUI, you just need to put regular JTextFields in your GUI and in the creation code, you will specify the constructor of IntegerField.
There is a componant for that: formatted textfield:
http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html
Use JFormattedTextField capabilities. Have a look at example.

Time-inputfield for quick entering

I want a quick-to-use way for entering times down to centiseconds. Entering digits should push them in from the right and automatically add leading zeros, "." and ":" as needed, so for example:
"" => "0.03" => "0.31" => "3.14" => "31.41" => "3:14.15"
Also, entering "f" should result in "DNF" ("did not finish"):
"3:14.15" => "DNF" => "0.04"
My code below "works", except it always puts the cursor at the end (because I full-replace), which is not nice when someone tries to edit in the middle. Is there an easy way to keep the cursor where it should be? And more importantly, is my whole approach proper at all or I should really do this differently? I've tried many ways before (JFormattedTextField and Formatters, DocumentFilter, DocumentListener, etc), some because they were suggested here for similar things, but couldn't get them to work.
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
class TimeField extends JTextField {
public static void main ( String[] args ) {
JFrame frame = new JFrame();
frame.add( new TimeField() );
frame.add( new TimeField(), BorderLayout.SOUTH );
frame.pack();
frame.setDefaultCloseOperation( frame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
TimeField () {
super( 10 );
setHorizontalAlignment( RIGHT );
setFont( new Font( "MONOSPACED", Font.BOLD, 32 ));
((AbstractDocument) getDocument()).setDocumentFilter( new DocumentFilter() {
public void insertString ( DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr ) throws BadLocationException {
replace( fb, offset, 0, string, attr );
}
public void remove ( DocumentFilter.FilterBypass fb, int offset, int length ) throws BadLocationException {
replace( fb, offset, length, "", null );
}
public void replace ( DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs ) throws BadLocationException {
fb.replace( offset,length, text, attrs );
if ( text.contains("f") ) {
fb.replace( 0, getText().length(), "DNF", null );
return;
}
text = getText(); // get current text
text = text.replaceAll( "\\D", "" ); // remove non-digits
text = text.replaceAll( "^0+", "" ); // remove leading zeros
while ( text.length() < 3 ) text = "0" + text; // make at least three digits
text = text.replaceAll( "(.)(..)$", "$1.$2" ); // add point if necessary
text = text.replaceAll( "(.)(..\\.)", "$1:$2" ); // add colon if necessary
fb.replace( 0, getText().length(), text, null ); // replace original with formatted
}
} );
}
}
Edit:
I tried JFormattedTextField before, here's my best attempt. I can enter digits and when the focus leaves the field, valueToString gets called and adds point+colon which is then displayed. But I'd like this to be done during editing, not after. I must be missing something, as MaskFormatter can apparently do that.
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
class TimeField extends JFormattedTextField {
public static void main(String[] args) {
//Create Event Disptach Thread for swing UI and its components to run on
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
JFormattedTextField ftf = new JFormattedTextField(new TimeFormatter());
ftf.setHorizontalAlignment(JTextField.RIGHT);
ftf.setFont(new Font(Font.MONOSPACED, Font.BOLD, 32));
ftf.setColumns(10);
frame.getContentPane().add(ftf);
frame.getContentPane().add(new JButton("foo"), BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
static class TimeFormatter extends DefaultFormatter {
public Object stringToValue(String text) {
System.out.println("stringToValue(" + text + ")");
return text == null ? "" : text.replaceAll("\\D", "");
}
public String valueToString(Object value) {
System.out.println("valueToString(" + value + ")");
return value == null ? null : format((String)value);
}
private String format(String text) {
text = text.replaceAll("\\D", ""); // remove non-digits
text = text.replaceAll("^0+", ""); // remove leading zeros
while (text.length() < 3) text = "0" + text; // make at least three digits
text = text.replaceAll("(.)(..)$", "$1.$2"); // add point
text = text.replaceAll("(.)(..\\.)", "$1:$2"); // add colon if necessary
return text;
}
}
}

Categories