Wait for TextField input, before continuing with the code - java

I have a Graphical User Interface that has a TextField, my code looks as following:
int port = 0;
try{
port = Integer.parseInt(frame.textfieldInput.getText());
}
catch(NumberFormatException npe)
{
System.out.println("Error! parse exception");
}
System.out.println("The Port is " + port); //is 0
I have to assign the value '0' to port, because otherwise the code wont compile, because the variable wouldn't be initialized.
Because the TextField is empty at the beginning of the Program, getText() wont get a value, which is why port stays '0'.
Is there any way to wait for the input before the code continues?

Found a solution, this is how I solved it:
I created a global variable outside of my ActionListener:
public String value = "";
public void createInput() {
buttonInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
value = textfieldInput.getText();
}
});
}
named 'value'.
in my public static void main(String[] args) I declared the following:
while(frame.value.equalsIgnoreCase(""))
{
try
{
System.out.println("waiting...");
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
System.out.println("interrupted");
}
}
I just have to clear the variable 'value' everytime I used it, so it is empty again for future uses.
I tis not the best way to solve it, but it worked for me.

Below code may give you some idea to more efficient way to get value on focus lost.
JFrame frame = new JFrame();
frame.setSize(50, 50);
TextField field = new TextField();
field.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
// continue from here
System.out.println(field.getText());
}
#Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
}
});
frame.getContentPane().add(field);
frame.setVisible(true);

Related

Using a varible in another method whose value has been changed in an actionListener i

I need to use the String P in the following code in another method(arrive). String P has been assigned a new value in the actionListener.
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent hh)//Method to perform action on clicking
{
f=cb.getSelectedIndex();
for(i=0;i<c;i++)
{
if(i==f)
{
P=copy2[i];
}
}
try
{
frame.pack();
frame.dispose();
obj.arrive();
}
catch(IOException e)
{
e.printStackTrace();
}
}
});
Any suggestions would be valuable.

Java - onFormClosing conversion C# to Java

I would like to ask if someone can help me with the following: I am trying to complete the following in Java. I am still quite new to Java and I hope that this can be achieved. Please note that this C# code might not be 100% correct, but I hope you understand what I am trying to achieve. Thank you in advance for your assistance.
//C#
//Form one
public void onFormShown(EventArgs e)
{
if (this.User == null)
{
frmTwo f = new frmTwo();
f += f_onFormClosing(EventArgs e);
this.Hide();
}
}
private void f_onFormClosing(EventArgs e)
{
this.Show();
this.User = f.User;
}
//frmTwo
private void btnClose_Click(EventArgs e)
{
this.Close();
}
EDIT:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
if (loginUser.get().getUserLogin() == null) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Where loginUser is private AtomicReference<Singleton>
//loginUser = new AtomicReference<Singleton>();
//The reason for the data type here is to pass
//the object by reference, log the user in and change
//the value of the Main form's variable
LoginForm login = new LoginForm(loginUser);
login.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent we) {
//here I need to place the logic of
//setting the Main form's 'loginUser'
// object to the value generated in
//the Login form
}
});
}
});
this.setVisible(false);
}
}

Java: I can't put my actionlistener outside the constructor

public Server(){
start.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
try{
port = Integer.parseInt(portInput.getText());
}
catch(NumberFormatException e){
text.append("");
}
}
});
}
Having the actionlistener inside the constructor, I can't use the append method becacuse it tells me to add a Server cast to text.append("");
When I do this it tells me I "Cannot cast from JTextArea to Server"
When I move the action listener outside of the constructor it gives me an error and basically forces me to put the action listener inside the constructor. So what I want is to be able to have the action listener outside the constructor so I can call the append method inside the actionlistener.
At this point I'm not sure what to do. I'm sure its something minor, but I just can't figure it out. Any help please?
I'm going to first present working code based for the addActionListener in constructor case, I took the liberty of introducing missing fields.
public class ServerGUI {
private final JButton startServer = new JButton("Start server");
int port;
private JTextField portInput = new JTextField();
private JTextArea eventsLog = new JTextArea();
public ServerGUI(){
startServer.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
try{
port = Integer.parseInt(portInput.getText());
}
catch(NumberFormatException nfe){
appendEventsLog("");
}
}
});
}
private void appendEventsLog(String msg) {
String text = eventsLog.getText();
eventsLog.setText(text + "\n" + msg);
}
}
The problem here was that appendEventsLog is not a member of JTextArea but a member of ServerGUI.
For the second case assigning ActionListener to JButton outside the constructor you have to use static code block or what I prefer initialise method
public class ServerGUI {
private final JButton startServer = new JButton("Start server");
int port;
private JTextField portInput = new JTextField();
private JTextArea eventsLog = new JTextArea();
public ServerGUI(){
initalise();
}
private void initalise() {
startServer.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
try{
port = Integer.parseInt(portInput.getText());
}
catch(NumberFormatException nfe){
appendEventsLog("");
}
}
});
}
private void appendEventsLog(String msg) {
String text = eventsLog.getText();
eventsLog.setText(text + "\n" + msg);
}
}
You are actually not handing over any string at
eventsLog.appendEventsLog("");
I´m not shure if it has to do with your problem or if you just forgot to type it.

Restrict Input of JTextField to Double Numbers?

In java , i am trying to make simple currency converter, but for that i need a text field which can restrict input to numbers only and more importantly double numbers. I tried using JFormatedTextField but it only format the input after you have done your input and click elsewhere but i need to restrict TextField to consume() each invalid character while doing input.
Possible Attempts:
Using JFormatedTextField:
JFormatedTextField textField = new JFormatedTextField(new DoubleFormat());
textField.setBounds(190, 49, 146, 33);
frame.getContentPane().add(textField);
textField.setColumns(10);
Using KeyTyped Event:
char c = arg0.getKeyChar();
if(!(Character.isDigit(c) || c == KeyEvent.VK_BACK_SPACE || c== KeyEvent.VK_DELETE)){
arg0.consume();
}
Using KeyTyped Event with regex:
if(!((textField.getText().toString+arg0.getKeyChar()).matches("[0-9]*(.[0-9]*)?"))){
arg0.consume();
}
Second and third attempt were close but then second attempt failed on point values and third attempt always read first character on textField no matter what it is, So any suggestions ? i am not very fond of JAVA GUI so kindly be patient.
If you know how many places before and after decimal point you want, you can also use MaskFormatter. For example:
JFormattedTextField field = new JFormattedTextField(getMaskFormatter("######.##"));
(...)
private MaskFormatter getMaskFormatter(String format) {
MaskFormatter mask = null;
try {
mask = new MaskFormatter(format);
mask.setPlaceholderCharacter('0');
}catch (ParseException ex) {
ex.printStackTrace();
}
return mask;
}
However it will chenge a look of JTextField, so it will be always visible 000000.00 in it.
EDIT
Another way, not too elegant, but in my opinion working. Try with DecumentListener, maybe it will suit your needs:
field = new JFormattedTextField();
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
Runnable format = new Runnable() {
#Override
public void run() {
String text = field.getText();
if(!text.matches("\\d*(\\.\\d{0,2})?")){
field.setText(text.substring(0,text.length()-1));
}
}
};
SwingUtilities.invokeLater(format);
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
}
});
I used regex: \\d*(\\.\\d{0,2})? because two decimal places is enough for currency.
You would need to use a DocumentFilter. Read the section from the Swing tutorial on Implementing a DocumentFilter for an example to get you started.
Your implementation will be more complex because you will need to take the text already in the Document and then insert the new text in the appropriate location in the String and then invoke Double.parseDouble(...) on the String to make sure it is a valid double value.
If the validation succeeds then you continue with the insertion otherwise you can generate beep.
You can add a key listener to the text field and implement the keyReleased() method to determine if they value in the text field is a double after every key stroke by the user.
public class CurrencyJTF extends JFrame {
JButton jButton = new JButton("Unfocus");
final JFormattedTextField textField = new JFormattedTextField(new DecimalFormat());
double lastDouble = 0.0;
public CurrencyJTF() throws HeadlessException {
textField.setColumns(20);
textField.setText(lastDouble + "");
this.setLayout(new FlowLayout());
this.add(textField);
this.add(jButton);
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
handleKeyReleased();
}
});
}
private void handleKeyReleased() {
String text = textField.getText();
if (text.isEmpty()) return;
try {
lastDouble = Double.parseDouble(text);
} catch (NumberFormatException ex) {
textField.setText(lastDouble + ""); // or set to other values you want
}
}
public static void main(String[] args) {
JFrame frame = new CurrencyJTF();
frame.setVisible(true);
frame.pack();
}
}
You can write your own KeyListener something like that:
public class DoubleNumbersKeyListener implements KeyListener {
final HashSet<Character> valid_keys = new HashSet<>();
final ArrayList<Character> sequence = new ArrayList<>();
public DoubleNumbersKeyListener() {
valid_keys.add('.');
valid_keys.add('0');
valid_keys.add('1');
valid_keys.add('2');
valid_keys.add('3');
valid_keys.add('4');
valid_keys.add('5');
valid_keys.add('6');
valid_keys.add('7');
valid_keys.add('8');
valid_keys.add('9');
valid_keys.add((char) KeyEvent.VK_BACK_SPACE);
valid_keys.add((char) KeyEvent.VK_DELETE);
}
#Override
public void keyTyped(KeyEvent event) {
char c = event.getKeyChar();
if (!valid_keys.contains(c)) {
event.consume();
} else {
if (c == KeyEvent.VK_DELETE || c == KeyEvent.VK_BACK_SPACE) {
if (!sequence.isEmpty()) {
char last = sequence.remove(sequence.size() - 1);
if (last == '.') {
valid_keys.add(last);
}
}
} else {
sequence.add(c);
if (c == '.') {
valid_keys.remove(c);
}
}
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}

Barcode scanner inserting character by character

Ive been trying a while and cant work out a way to get the text out of a textbox only after the barcode scanner has finished scanning. I am using Swing Framework and Java. My Code works if the text is pasted (Ctrl + V) into the JTextbox but the barcode scanner just does not work as my methods run for every couple of characters of the barcode in turn.
textField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
// warn();
}
public void removeUpdate(DocumentEvent e) {
// warn();
}
public void insertUpdate(DocumentEvent e) {
warn();
}
public void warn() {
input = textField.getText();
SwingUtilities.invokeLater(doUpdate);
}
});
Where input is a variable which I use
The doUpdate method which gets executed is here
final Runnable doUpdate = new Runnable() {
#Override
public void run() {
System.out.println(input + " Is being processed");
textField.setText("");
System.out.println(input.length());
lblStatus.setIcon(new ImageIcon(Main.class
.getResource("/com/daniel/status2.png")));
// frame.getContentPane().add(lblStatus2, BorderLayout.EAST);
if (input.length() <= 4) {
lblStatus.setIcon(new ImageIcon(Main.class
.getResource("/com/daniel/status3.png")));
return;
}
// TODO START
if (!content.containsKey(input)) {
content.put(input, "1");
} else {
Integer i = Integer.valueOf(content.get(input));
i++;
lblStatus.setIcon(new ImageIcon(Main.class.getResource(i
+ ".png")));
playSound(i + "");
if (i.equals(6)) {
i = 0;
}
content.put(input, String.valueOf(i));
}
System.out.println(content.get(input));
Properties properties = new Properties();
for (Entry<String, String> entry : content.entrySet()) {
properties.put((String) entry.getKey(), entry.getValue());
}
try {
properties.store(new FileOutputStream(path
+ "data.properties"), null);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
All Im asking is how do I run a method with a String from the text box only after the barcode reader has finished
It's been a while since I used a barcode reader, but when I did each scan was a line. That is, each scan was a sequence of characters terminated by the new line character. So, you could test the input and only invoke doUpdate when you detect the new line character. That said, you might need to set a property on the text box to allow the new line character and remove it when detected.
You need someway to inject a delay between each update of the DocumentListener and the time your inspect/use the value from the text field.
A simple solution is to use a Swing Timer with a short delay (you can play around with this to find the threashold which is most useful to you). Each time the DocumentListener is notified, you simply reset the timer (start it again), so that it won't trigger until after the delay you specified has occurred, at which time you can read the text from the field.
public class TestPane extends JPanel {
private Timer updateTimer;
private JTextField field;
private JLabel label;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
updateTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(field.getText());
}
});
updateTimer.setRepeats(false);
label = new JLabel("...");
field = new JTextField(14);
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
processUpdate();
}
#Override
public void removeUpdate(DocumentEvent e) {
processUpdate();
}
#Override
public void changedUpdate(DocumentEvent e) {
processUpdate();
}
});
add(field, gbc);
add(label, gbc);
}
protected void processUpdate() {
updateTimer.restart();
}
}
You could test this using Robot, which can be used to inject key strokes into the event queue with a specified delay, or just run your scanner at it.
See How to use Swing Timers for more details
You should also attach a ActionListener to the field and see if the scanner triggers the ActionListener, which would be a simpler solution over all

Categories