My title is somewhat cryptic but I couldn't come up with a clear one.
First, two code snippets to establish a point of reference (hopefully I have no typos):
Input with Scanner
'''
Scanner sc = new Scanner(System.in);
for (int i=0; i<10; ++ i) {
System.out.print("Please input a value:");
String answer = sc.next();
// do something with this string
}
...
Input with JOptionPane:
...
for (int i=0; i<10; ++ i) {
String answer = JOptionPane.showInputDialog("Please input a value");
// do something with this string
{
So, in the above samples we're asking a user to enter a value a fixed number of times. How can I implement the same kind of functionality in a Swing application?
I have no problem creating a JFrame with JPanel (as its content pane) and adding JLabel (with prompt) and JTextField to this panel. I can also create ActionListener for the text field which ActionPerformed method to retrieve the value and process it. String processing is not a long-running task so I do not believe I will need a separate worker thread.
Since we can't really force user to do anything, I plan to use javax.swing.Timer to ensure a timely response.
What I do not understand is how to implement the loop or any other form of control to ensure that a user enters (and the program retrieves) the value the exact number of times. How do I inject such logic into an event-driven system?
Once I set-up the GUI part and submit its instance to be invoked on EDT I seem to be relinquishing all control.
Do I initially submit my text field with setEditable set to false and then create a loop that will invokeAndWait a Runnable to enable the edit (and disable it back in the ActionPerformed)?
Please point me into the right direction.
Well it depends on how you want to achieve it...
You could...
Provide the required number of fields (10 in your example) and a JButton, so that until all the fields are filled out, clicking the button will simply provide the user with a message and re-focus the invalid field...
You could...
Provide the user with a single field (and label) and button. Until they fill out the field, pressing the button prompts them and re-focuses the field.
When the user fills out the required information and clicks the button, you increment a counter, reset the field and carry on until your counter reaches it's limit...
You could...
Use a JTable which has only one column and five rows...this is simplified (depending on your perspective) solution to the first solution...
Related
I'm writing a program using JavaFX and I currently have three TextFields. When you press enter while any of the text fields are focused, there is an EventHandler which calls the appropriate method for each field. There is no submit button because I want it to submit each input separately (that's just how I made the rest of the program) to be validated and return a String containing any errors in the input. If the users input is invalid, it resets it to the last valid value it had.
However, when testing I found that sometimes I just click somewhere else (such as the next field) rather than pressing enter, so I wanted to implement the same function as pressing enter but when the user clicks outside the field. There is a MouseClicked event on the root that I have attempted to make it submit the input for all of the fields at once which works, but if any field has not been filled in, then it will be unsuccessful and return an error message (which might confuse a user).
Additionally, if the user clicks inside the TextField again, say to delete something from the middle of the word, the event will be triggered and the field will be reset to the last valid value if the current input was invalid.
I've considered using a MouseExited event on each field, but I think that might be triggered by the cursor leaving the field, rather than a click outside of the field.
What would be a good way of doing this, while minimising the number of event methods in my program?
I have a large array of numbered buttons that are used to get an integer. Is there anyway I could write a method which activates these buttons, waits until a user has clicked one, deactivates them, and return the integer that was pressed.
The method would be similar to JOptionPane.showInputDialog in that it brings up a UI then return an int (instead of a string) when the user makes an input.
Why do I want to do this instead of just running out the program through the listener class? Long story short this array of buttons is used to get ints for many different purposes and the code that runs afterward is very different depending on where in the program the buttons are used. I have written some of the code using a switch statement in the listener so that it runs the appropriate code. However it is getting incredibly hard to read and confusing to write. Having a method that returns an int as I have described above would greatly simplify the program.
You can remove a listener and add a new one. But if you want to work with return values you could use an ArrayBlockingQueue. The listener you add to your buttons could put the int value into the blocking queue. And in your main thread you can then take a value out of the queue. The take method will pause the main thread until a button was pressed.
I´ve been working on a GUI and I´ve run into some problems with a JMenu. The GUI is in a separate class that takes all the actions of the program from the rest of the classes. My problem with using the menu is that I want it to do 2 things: first, to show the correct panels based upon a user choice and second, wait for user input to complete the chosen task.
I´ve arranged it into 13 different if.. else clauses depending on the user choice, this part works correctly with the nescessary input options (panels) shown that the user need to input data.
Part two when the user sees the right panels and wants to input information (int and Strings) is where things don´t go as intended. Instead of waiting for user input and then take actions based on those data the program rushes forward and continues. Since no data is entered, needless to say, the output is not the intended one.
I´ll provide part of the class as it´s quite large.
class Employee implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("1"))
{
panelB.setVisible(false);
panelC.setVisible(false);
panelD.setVisible(false);
display.setText(bank.infoBank()); }
else if(e.getActionCommand().equals("2"))
{
panelB.setVisible(true); //Show all panels
panelC.setVisible(true);
panelD.setVisible(true);
label2.setText("Accountnumber: ");
text2.setText("");
display.setText("");
}
...
else if(e.getActionCommand().equals("5"))
{
panelB.setVisible(true);
panelC.setVisible(false);
panelD.setVisible(true);
display.setText("");
if(e.getActionCommand().equals("Ok") && !pNrText.getText().isEmpty()) //This is a JButton that when pressed should send the data to the method
{
if(checkInput(pNrText) == true) //Method to validate input
{
pNr = Long.parseLong(pNrText.getText()); //pNr is an input field
bank.addSavingsAccount(pNr); //this is a method from another class
}
else
{
JOptionPane.showMessageDialog(null, "Only digits permitted!");
}
}
This last part (actioncommand equals 5) is one of the places where the program doesn´t wait for the user to input anything before it continues and thus receives no input at all to process.
This is part of an ATM-program built around different JMenus, in another place where an JRadioButton is used it works as intended but I can´t get it to work using the JMenu and I don´t want to use a JRadioButton with so many choices(13).
Any input greatly appreciated!
/Johan
"This last part (actioncommand equals 5) is one of the places where the program doesn´t wait for the user to input anything before it continues and thus receives no input at all to process."
else if(e.getActionCommand().equals("5")) {
panelB.setVisible(true);
panelC.setVisible(false);
panelD.setVisible(true);
display.setText("");
if(e.getActionCommand().equals("Ok") {
I don't know why you would expect this behavior. This is not a console program where a scanner waits for input. Event driven programming doesn't work like that. One event get's one response. There's no waiting. Everything in the actionPerformed happens exactly once. That means when you press 5, the corresponding if will perform. The OK-if will never be performed because no event will ever reach it because it's trapped in the 5-if. Quickes fix, would be to give the OK-block it's own else-if on the same level as the 5-if
Like I said in my comment. Avoid all these if statement. Add an anonymous listener to each menu item.
okItem.addActionListener(new ActionListener(){
public void actionPerforemd(ActionEvent e) {
}
});
But you can even excel beyond this and use Action. Personally I prefer to go this route for menu items, for a number of reasons.
Also as an aside, you should be using a CardLayout to switch between panels.
I will do my best to explain-- I am trying to make a choose-your-own-adventure type game while using a TextField and a TextArea, where what is written in the TextField is appended into the TextArea (this I know how to do via ActionListener).
However, I need to have the TextArea start with a pre-written 'intro', which asks the user at the end if they want to continue or not. Therefore, I need it to be able to scan the user's response ('yes' or 'no') and choose the appropriate selection of pre-written text to follow.
I don't want to overwrite what is already in the TextArea, I want to add to it. I suppose what I'm confused about it how I'm supposed to lay out the entire file so that it functions properly, because the different choices for the adventure span different methods. Having
"String text = textField.getText();" only within the actionPerformed method means I can't use 'text' elsewhere, but moving that line up with my other variables tells me it can't reference the field before it's defined.
I am fairly new to Java and am working on this as a project for a non-programming school course. I've been through many iterations thus far and this is what seems to be my final attempt, as I've remade it repeatedly and don't have much time left. :(
Your questions/comments and my attempts to answer:
I am trying to make a choose-your-own-adventure type game while using a TextField and a TextArea, where what is written in the TextField is appended into the TextArea (this I know how to do via ActionListener).
As per my comment, be sure to create a Swing GUI which would use a JTextField and a JTextArea. You would then add your java.awt.event.ActionListener to the JTextArea, and the ActionListener would respond whenever the user pressed <ENTER> within the JTextField.
However, I need to have the TextArea start with a pre-written 'intro', which asks the user at the end if they want to continue or not. Therefore, I need it to be able to scan the user's response ('yes' or 'no') and choose the appropriate selection of pre-written text to follow.
This can be done easily, but sounds as if you may be trying to shoe-horn a linear console type program into a GUI. If so, consider reconsidering your program design since what works best for one often doesn't work well for another. If you do re-write, then you should consider redoing most including your program flow, but excepting perhaps the "model" portion of your previous program, the "business logic" that underlies everything.
I don't want to overwrite what is already in the TextArea, I want to add to it. I suppose what I'm confused about it how I'm supposed to lay out the entire file so that it functions properly, because the different choices for the adventure span different methods. Having "String text = textField.getText();" only within the actionPerformed method means I can't use 'text' elsewhere, but moving that line up with my other variables tells me it can't reference the field before it's defined.
Again as per comments a JTextArea has an append(String text) method that will add new text to existing text that is already displayed in your JText Area. So on that note, your ActionListener's actionPerformed method could be very simple and look something like:
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
textArea.append(text):
}
Although you may need to add line feeds, "\n" either before and/or after the text you are going to append.
I have developed virtual keyboard module, it contains 2 classes
KBM (the module itself) (on enter press it sets value of String data to the text i typed in KBMListener, and Boolean changed to true in KBMListener)
KBMListener
MainFrame
What is doing mainFrame:
When I run the program MainFrame loads the GUI and starts "while(true)" loop in "public void run()". This loop look like :
while(true){
if(status_changed){
jTextArea.setText(getKbml().getData());
getKbml.setStatus_changed(false);
}
sleep(500);
}
The boolean status_changed is changed in a keyboard Listener.
KBM is the virtual keyboard. When the user type text and press enter, it set the String data to text typed and boolean status_changed to true in KBMListener.
KBML just connects the MainFrame with KBM and loads the keyboard from KBM everytime the user clicks into textarea in mainframe.
What I want is every 0.5 sec or instantly get value to mainframe when enter is pressed.
While loop is working good, but cpu usage is around 12% on 1.6GHz dualcore processor.
I heard about callback but I can not understand how it works. I hope somebody can help me... Try to avoid document listener please.
What you'll want to look into is the Observer design pattern. It uses an interface to notify 'listeners' of changes, and is often the answer to infinite loops. You can find a simple implementation example + more information here : http://java.dzone.com/articles/design-patterns-uncovered
Or simply search the web for "observer pattern java".