I've just taken up playing with GUIs, and I'm experimenting with getting text input from the user, and assigning it to a variable for later use.
Easy, I thought. Wrong, I was.
I wanted my frame to look something like:
public class firstFrame extends JFrame {
JTextField f1 = new JTextField();
String text;
public firstFrame(String title) {
super(title);
setLayout(new BorderLayout());
Container c = getContentPane();
c.add(f1);
text = f1.getText();
System.out.println(text);
}
}
Where the variable text would get whatever text the user typed in, then print it out to the console. Simple.
I've got a feeling I'm missing something pretty fundamental here, and would appreciate it if anyone could fill me in on what that something is.
The variable won't be updated until an event occurs on the component. For this a DocumentListener or ActionListener can be used
f1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = f1.getText();
...
}
});
getText() only get the text that is in the JTextArea at the time it is called.
You are calling it in the constructor. So when you instantiate new firstFrame, there is no initiital text.
One thing to keep in mind is that GUIs are event driven, meaning you need an event handler to capture and process events.
One option is to add an ActionListener to the JTextField so when you press Enter after entering text, the text will print.
f1.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String text = f1.getText();
System.out.println(text);
}
});
See more at how to Create GUI with Swing and Writing Event Listeners
Related
Is there any way to get the source of an event? I know event.getSource() however, is there any way to convert it into a string?
For example, if the source is a button, button1, is there anyway to assign the value button1 to a string variable? (I'm dealing with a lot of buttons and so, I can't write if statements)
For the sake of clarity:
The getSource() method returns the object from which the Event initially occurred. You could use this to get some sort of property from the element, like the text inside a label or the name of a button.
These are Strings, but if you chose to go this route, I would make sure you pick something that is uniform across all components that will be calling that ActionListerner.
This is where getActionCommand() might come in handy. You can set unique 'identifiers' when components are created, and the access them later.
JButton button = new JButton("Button");
button.setActionCommand("1");
JButton button = new JButton("Button");
button.setActionCommand("2");
Then you can compare these later using any method you like, or you could do something fancy, like this (because you said you didn't want to use if-else statements):
String command = e.getActionCommand();
int i = Integer.parseInt(command);
switch (i) {
case 1: // do something
break;
}
According to the Java docs:
Returns the command string associated with this action. This string allows a "modal" component to specify one of several commands, depending on its state. For example, a single button might toggle between "show details" and "hide details". The source object and the event would be the same in each case, but the command string would identify the intended action.
Keep in mind that I think this is best approach only if you are using one ActionListerner for lots of components. As another answer pointed out, you could just make unique ActionListeners per each button.
Hope this helps you!
You can pass anything you want to an action listener through the constructor, as DaaaahWhoosh stated in his comment.
package com.ggl.fse;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ButtonActionListener implements ActionListener {
private String buttonText;
public ButtonActionListener(String buttonText) {
this.buttonText = buttonText;
}
#Override
public void actionPerformed(ActionEvent event) {
// TODO Auto-generated method stub
}
}
The buttonText String will be available in the actionPerformed method.
You can use a specific ActionListener for each JButton. Try this code:
private static String text;
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(200, 200, 200, 200);
frame.setLayout(new BorderLayout());
JButton button1 = new JButton("Button 1");
button1.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
text = button1.getText();
JOptionPane.showMessageDialog(null, "Text is: " + text);
}
});
JButton button2 = new JButton("Button 2");
button2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
text = button2.getText();
JOptionPane.showMessageDialog(null, "Text is: " + text);
}
});
frame.add(button1, BorderLayout.NORTH);
frame.add(button2, BorderLayout.SOUTH);
frame.setVisible(true);
}
I was reading about Swing Timers and the example really looks nothing like I was trying to do so I found it logically confusing to apply it to my program. I'm starting to think I don't even need a timer for this.
Here is what I am trying to do:
I am making a JFrame program that has the user enter a credit card number into a JTextField. Before they do this there is a JLabel that says "Please enter your number into the text field", then once they enter this into the field and hit enter, depending on whether my code determines that the card number is valid or not valid, the JLabel will change to "Invalid" or "Thank you, processing."
However, I have unsuccessfully found a way to make it change text based, it just seems to stay with whatever text I initially give it.
So could someone please look at my code and change it to do what I am asking? That would be excellent. You guys have been helpful in the past.
public class CreditGraphics {
public String cardNum;
public JFrame frame;
public JPanel panel;
public JLabel label;
public JTextField text;
public Timer timer;
public CreditGraphics() {
frame = new JFrame("HI");
panel = new JPanel();
label = new JLabel();
text = new JTextField(16);
panel.add(label);
panel.add(text);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
label.setText("Hi");
label.setText("Hello");
text.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardNum = text.getText();
timer = new Timer(2000,this);
timer.setInitialDelay(1000);
timer.start();
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new CreditGraphics();
}
});
}
public void checkCard(){
}
}
You have some major problems with your Timer's ActionListener as it is adding the anonymous inner ActionListener object, the this in the Timer's constructor, to itself. So it will call the very same actionPerformed inside the Timer that is called by the JButton that starts the Timer -- quite confusing. If your program were to need a Timer, you would do well to make sure to give it its own ActionListener, and not the same ActionListener that you add to your JButton as you're doing now.
Most importantly, do you even need a Swing Timer? I don't think so since you don't appear to be wanting an action repeatedly happening every xxx milliseconds, or an action that occurs once after xxx milliseconds, and since all you want to do is change the text. I suggest that instead you simply change your JLabel's text in the anonymous inner ActionListener class, and just leave it at that. If your requirements are different, then you will want to clarify and expand on your question.
So in semi-pseudocode, something like:
public void actionPerformed(ActionEvent e) {
String userText = text.getText();
if (testIfTextValid(userText)) { // some method to test if input OK
label.setText(INPUT_VALID); // String constant for JLabel to display
// here pass the userText to other parts of your code that needs to use it
} else {
label.setText(INPUT_INVALID);
}
}
I am really new in Java, and just practising ActionListeners. As the part of the application I work on, I will have a JTextField that lets the user to search a name, and then a JTextArea to show the result of the search. I have a api for searching and fining the the names, only problem is to connect the widgets to the methods and action listener file.
Here is some parts of the code:
Widget File:
//Text Field
JTextField searchbox = new JTextField();
leftSide.add(searchbox, cnt);
String userText = searchbox.getText();
ActionListener sendsText = new SearchListener(search box);
searchbox.addActionListener(sendsText);
//TextArea
JTextArea stationList = new JTextArea(12, 0);
leftSide.add(stationList, cnt);
String entered = userText;
stationList.append(entered);
SearchListener:
public class SearchListener implements ActionListener {
private JTextField searchbox;
private JTextArea stationList;
public SearchListener(JTextField search box) {
this.searchbox = searchbox;
}
public void ListF(JTextArea stationList){
this.stationList = stationList;
public void actionPerformed(ActionEvent event) {
XXXX<NAMES> stations = HHHH.SimilarNames(searchbox.getText());
for (NAMES station : stations) {
//System.out.println(station);
*Problem*> String result = (searchbox.getText());
*Problem*> stationList.append(result);
}
So in this program, the TextFiels is connected and the ActionListener working, but it prints out the list on Similar names in the CMD, (I commented it here). But I want it to send the list back to the Text Area in the API.(Widget File). So I am not sure my ActionListener method at the top of the SearchListener is right. Also the Problem> in the code is where I tired to pass the search result to the text field, which doesnt work.
So anyone know how to fix it?
Thank is advance.
I think you may be twisting a few things around, but perhaps this is what you're trying to accomplish:
A search field who's value determines what the text area is populated with.
If this is the case, then a few things have to change. First, only code within the ActionListener will be axecuted upon UI events, so there is no reason to call getText() on any of the UI elements during initialization.
Second, adding a button to this UI greatly simplifies the logic here. If attaching the listener to the search box, issues begin to arise such as "when do I know the user is done entering text?" and "How do I handle partial text?", however using a "Search" button puts this logic in the hands of a user.
Once the "Search" button is clicked, the action event from the listener that is attached to the button will trigger, and the stationListArea will be populated with the results of similarNames(<text from search box>).
Note that though what is shown below is not the cleanest way to perform this task (which would involve fields and anonymous inner classes), it is straightforward and easy to understand.
Widget (not sure what cnt was, so I omitted in in sample code below)
//Create the search text box
JTextField searchBox = new JTextField();
leftSide.add(searchBox);
// Create a button that will serve as the "Action" for the search box
JButton searchButton = new JButton("Search");
lefSide.add(searchButton);
// Create the station-list text area that will display text
// based on results from the search box
JTextArea stationListArea = new JTextArea(12, 0);
leftSide.add(stationListArea);
// Create a listener that listens to the Button, then performs an
// action from the search box to the text area
ActionListener searchButtonListener = new SearchListener(searchBox, stationListArea);
searchButton.addActionListener(searchButtonListener);
SearchListener
NOTE: Logic here will continue adding text into your stationListArea every time the button is clicked and HHHH.SimilarNames() returns a value. To have the stationListArea just update with the new text every time, replacing the old, add a stationListArea.setText("") at the beginning of actionPerformed().
public class SearchListener implements ActionListener {
private JTextField searchBox;
private JTextArea stationListArea;
public SearchListener(JTextField searchBox, JTextArea stationListArea) {
this.searchBox = searchBox;
this.stationListArea = stationListArea;
}
public void actionPerformed(ActionEvent event) {
XXXX<NAMES> stations = HHHH.SimilarNames(searchBox.getText());
for (NAMES station : stations) {
stationListArea.append(station);
}
}
}
Updated based on feedback in main comments
Your NAMES object needs some way to provide a String representation of itself. This way, you can then append that value to your text area..
public class SearchListener implements ActionListener {
private JTextField searchbox;
private JTextArea stationList;
public SearchListener(JTextField search box) {
this.searchbox = searchbox;
}
public void actionPerformed(ActionEvent event) {
XXXX<NAMES> stations = HHHH.SimilarNames(searchbox.getText());
for (NAMES station : stations) {
stationList.append(station.getLocationName()());
}
}
How can I put Caret in JTextArea while setEditable is disabled?
A sample code when I need Caret to be visible:
public void run(){
JFrame frame = new JFrame();
JTextArea text = new JTextArea();
text.setEditable(false);
String line = "added line";
text.append(line);
text.setCaretPosition(text.getCaretPosition() + line.length());
frame.getContentPane().add(text);
frame.setSize(300,300);
frame.setVisible(true);
}
What I want to achieve is that, when the user types within TextArea, characters must not be displayed. Typed characters are redirected to OutputStream and appropriate InputStream is received which will be displayed within TextArea. This works fine, but Caret is hidden because of setEditable(false).
text.getCaret().setVisible(true) and/or text.getCaret().setSelectionVisible(true)
Well, I put here a code fragment which shows the caret but don't let edit the JTextArea. I hope it helps you. It's a little trick which plays with the focus of the text area, when focus is gained, the edition is disabled; but when it's losed, the edition it's possible. In this way, the user is unable to edit it but can see the caret.
public void run() {
JFrame frame = new JFrame();
final JTextArea text = new JTextArea();
text.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent fe) {
text.setEditable(true);
}
public void focusGained(FocusEvent fe) {
text.setEditable(false);
}
});
text.setEditable(true);
String line = "added line";
text.append(line);
text.setCaretPosition(text.getCaretPosition() + line.length());
frame.getContentPane().add(text);
frame.setSize(300,300);
frame.setVisible(true);
}
Notice that the user can move the caret, but he/she can't edit the text
I tried the solution originally proposed by StanislavL. However, other issues emerged. For example, after leaving the JTextArea and focusing back later, the caret would turn invisible again.
I suspect that caret was not implemented as most people would expect to behave. While I saw some authors proposing to re-implement the caret, I successfully achieved visible caret behavior with following small listener:
textArea.getCaret().setVisible(true);
textArea.getCaret().setSelectionVisible(true);
textArea.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
textArea.getCaret().setVisible(true);
textArea.getCaret().setSelectionVisible(true);
}
#Override
public void focusLost(FocusEvent e) {
textArea.getCaret().setSelectionVisible(true);
}
});
On example above, I decided to keep the selection visible even if one leaves the text area.
I'm wondering if someone can help me out. I entered a character into a text area from a button, and want to use the string entered into the textarea to retrieve words from a list. Bear in mind, there could be numerous characters entered. Is it possible for a text area to detect when text has been entered and to action it?
You can add a DocumentListener to your JTextArea;
class YourClass {
...
public void attachTextAreaToPanel(JPanel panel) {
JTextArea textArea = new JTextArea();
textArea.getDocument().addDocumentListener(new MyDocumentListener());
panel.add(textArea);
}
}
class MyDocumentListener implements javax.swing.event.DocumentListener {
public void changedUpdate(javax.swing.event.DocumentEvent e) {
// text has been altered in the textarea
}
public void insertUpdate(javax.swing.event.DocumentEvent e) {
// text has been added to the textarea
}
public void removeUpdate(javax.swing.event.DocumentEvent e) {
// text has been removed from the textarea
}
}
Edit, this requires that you use Swing - and not AWT.
I assume you are refering to swing JTextArea ?
look at:
http://java.sun.com/docs/books/tutorial/uiswing/components/textarea.html
There is a part that is exactly what you are looking for.
Implements the TextListener for that textarea. Then use the conditions.
Otherwise implements ActionListener to your button. Then specify the action you want, while pressing your button.