I just have a very basic question about how to use textfields in Java. It's very simple, but the tutorials and other questions I've been looking for haven't been helpful, and I'm hoping that someone can explain things a little more clearly for me.
Right now I have the following code that I just sort of slapped together for the sake of example:
import javax.swing*;
public class testText {
public static void main(String[] args){
JFrame frame = new JFrame();
JTextField text = new JTextField();
frame.add(text);
frame.setVisible(true);
System.out.println(text.getText());
}
}
All I'm trying to do, is print what the user types into the text field in the console. But nothing happens when I type into the text field.
Now,based on the research I've done, I think the problem is that I'm not using an actionListener. The thing is, I really don't understand how those work, and I'm hoping someone can clarify for me.
I've been using this tutorial to try and figure things out, and particularly the TextDemo example they have near the top. I'm still kind of at a loss though, and I can't seem to find any way to use the actionlistener interface without breaking the program. If someone could either just explain simply and directly how to use the actionlistener to pull a string from a text field and then use it, or else point me to somewhere else where I can FIND a simple straightforward explanation, I would immensely appreciate it. I've been beating my head against this for five hours now with absolutely nothing to show for it, so I apologize for asking such a basic question but I'm at a loss.
An action listener will be called when an enter key is pressed while typing in the field. From the JTextfield Javadoc :
How the text field consumes VK_ENTER events depends on whether the
text field has any action listeners. If so, then VK_ENTER results in
the listeners getting an ActionEvent, and the VK_ENTER event is
consumed.
Here is your example modified to work with an action listener :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class testText {
public static void main(String[] args){
JFrame frame = new JFrame();
final JTextField text = new JTextField();
frame.add(text);
frame.setVisible(true);
text.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(text.getText());
}
});
}
}
And here is an object oriented complete example not relying only on a static main method.
Related
I need a way to create an ActionListener that when a JButton is pressed, it updates the content of 7 different JLabels to display the information in the form of text.
The data is retrieved from methods called from an external JAR file. The methods return ArrayList. I attempted to convert the ArrayList into a String, and tried to change the JLabel content with setText().
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import api.anAPI.THEAPINAME;
public class Controller implements ActionListener {
private MainGUI maingui;
private SubPanel subpanel;
private static THEAPINAME anAPI =new THEAPINAME("XyP0D75oRCGrLE78","x47ka5jmOGaJ2zvw");
static ArrayList<String> nameList =new ArrayList<String>();
private String names;
public Controller(MainGUI maingui,SubPanel subpanel){
this.maingui = maingui;
this.SubPanel = subpanel;
MainGUI.getSearchBtn().addActionListener(this);
nameList.addAll(anAPI.getNames());
for (String s: nameList){
names+= s+"\t";
}
}
public void actionPerformed(ActionEvent e) {
SubPanel.label1.setText(names);
//6 more Labels.
}
}
An additional, because I have 7 JLabels, would I need to do 7 getLabel methods? Or is there a way to get them all with just 1 method.
I am not entirely sure what I am doing incorrectly, it could be that the getMethods I used returned the wrong widget in question as the code for the GUI was not done by me but by a teammate and he had done a really poor job of making it clear for us.
UPDATE:
Fixed up the GUI to make it clearer, so I think that is no longer the problem. Now I think the problem might be that I did not convert the contents of the ArrayList into a String in the way I thought.
The desired function of the code is when the JButton is clicked on, the JLabels in question are all updated to their relevant data.
addController method
public void addController(Controller controller){
control = controller;
jb1.addActionListener(control);
}
You didn't really describe what the problem is of your current code.
You can add a method say getLabels() in SubPanel class to return all of its labels, or you can add a method setLabelText(String text) to set text for all of its labels by extending or directly modifying SubPanel class.
UPDATE
You have several very confusing parts in your code.
In your constructor, it should be this.subpanel = subpanel and then it should be maingui.getSearchBtn().addActionListener(this), also in method actionPerformed it should be subpanel.label1.setText(names). These might not be your problems though since you didn't say it's the code you're actually running.
Looks like that you haven't created any instance of class Controller thus the code in it never gets executed.
You need to have some code outside of you Controller class like this:
MainGUI maingui;
SubPanel subpanel;
// they're somehow initialized
Controller controller = new Controller(maingui, subpanel);
I'm on week three of a Java class. I am working on a class assignment that is due next week. I can complete the assignment without any problem using the console as output, which is acceptable. However, the Professor also suggested we research JTextArea and consider using it for our program output.
I found some code from a tutorial and was able to at least get a text block to appear with my first line of text to appear. But as I write the actual program, I need to continue to add additional lines to the text block as the program progresses.
When I attempt to use the following line of code in the main method to display text line 2, I get an error saying, "non-static variable textarea cannot be referenced from a static context".
textarea.append("Product1\t3\t$3.01\t$9.03");
Here is the code I have so far. Thanks in advance for any help!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ta extends JFrame{
JTextArea textarea;
public ta(){
setLayout(new FlowLayout ());
textarea = new JTextArea ("Product\tQuantity\tLine Cost\tOrder Cost\n", 5,30);
add(textarea);
}
public static void main(String[] args) {
ta gui = new ta();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(500,200);
gui.setVisible(true);
textarea.append("Product1\t3\t$3.01\t$9.03");
}
}
You can not reference textarea (which is a instance field) from a static context (ie from within main).
Instead, move textarea.append("Product1\t3\t$3.01\t$9.03"); to be within your constructor
public ta(){
setLayout(new FlowLayout ());
textarea = new JTextArea ("Product\tQuantity\tLine Cost\tOrder Cost\n", 5,30);
add(textarea);
textarea.append("Product1\t3\t$3.01\t$9.03");
}
Or provide some other "update" method for your ta class which you can call
You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others
I am using Substance L&F and I have set a JComboBox to editable so that i can select the value that i want from its popup, or type a new value in its Editor.
Typing a new value works fine, but if i want to delete a miss-typed letter from the Combo editor, and i click Backspace to do that it selects the letters in the editor instead of erasing them. Here is a screenshot :
I want the Combo editor to work like a JTextField when typing keyboard letters or Backspace or Delete in it, so is there a way to do that ? Or what is causing this?
See below for the importance of an SSCCE not everything that goes wrong is a bug, most of the times it something wrong in your actual code, which without an SSCCE we are non the wiser.
Seems to work fine for me:
On start up:
After selecting JComboBox and pressing Backspace:
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JComboBox jc = new JComboBox(new String[]{"Hello", "Bye", "World", "Cruel"});
jc.setEditable(true);
frame.add(jc);
frame.pack();
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new Test();
}
}
UPDATE
As per your comment:
I did not think it would work fine ! ... It is a problem in Substance;
the L&F i am using.
See below for details on the Bug:
Substance: Editable JComboBox does not support backspace key
As stated:
This behavior is by design. This is a "feel" part of Substance that
adds auto-completion on editable comboboxes.
Alternatively see my answer here for more L&Fs and/or a way to make your own
UPDATE 2:
Thanks to #Brad (for deciphering the bug log I linked from Substance :P) to fix this simply do:
UIManager.put( LafWidget.COMBO_BOX_NO_AUTOCOMPLETION, Boolean.TRUE );
UIManager.put(LafWidget.COMBO_BOX_NO_AUTOCOMPLETION, Boolean.TRUE);
This work for me!
This is the "main" class (doesn't contain the main method)
import javax.swing.*;
import java.awt.*;
//import java.lang.Object;
//import java.awt.event.ActionListener;
//import java.awt.event.;
public class Program {
public JFrame frame;
public JPanel header;
public JPanel text;
public JPanel body;
public JTextField input;
public JButton agregar;
public List listA;
public List listB;
public Program(String title) {
frame = new JFrame(title);
frame.setSize(500,600);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
header = new JPanel();
header.setBackground(new Color(255,204,50));
header.setBounds(0,0,500,100);
text = new JPanel();
text.setBackground(new Color(255,204,100));
text.setBounds(0,100,500,50);
text.setLayout(null);
//Inicializando la "entrada"
input = new JTextField(20);
input.setBounds(50,13,300,25);
text.add(input);
agregar = new JButton();
agregar.setBounds(360,12,80,25);
agregar.setText("Agregar");
text.add(agregar);
//Listo
body = new JPanel();
body.setBackground(new Color(255,204,150));
body.setBounds(0,150,500,450);
//Lo que está dentro del body
listA = new List(20);
body.add(listA);
listB = new List(20);
body.add(listB);
//Listo
//Añadir todos los paneles al frame principal
frame.add(header);
frame.add(text);
frame.add(body);
}
}
And this is the MAIN class (This one contains the main method):
public class Main {
public static void main(String[] args) {
new Program("Ordenamiento Recursivo");
}
}
Each time I run the application, the UI components are presented differently, please see attached screen shot.
Well, thanks to everyone who responded the post, I finished the program and I'm very happy with the final result, here it is:
In case anyone wants to take a look at the code, here it is: Link
Problems:
You're call setVisible(true) on your JFrame before adding components and this will lead to unreliable drawing of your program's graphics and is why you are seeing different results. Don't do this, but rather call it after you've added all to the top-level Window.
As the others are saying, read up and learn to use the layout managers.
Different windows with the same code?
I think that is very simple and possible by implements CardLayout
I'd suggest don't opening a new Top-Level Container, only if is there really important reason then use JDialog or JOptionPane
Be sure to construct the GUI on the EDT. Not doing so can cause unpredictable results.
Call pack() after the components are added using layouts and then call setVisible(true).
You will need a layout manager for your form so setting the layout manager to null is not the thing to do.
Work in progress here ... https://gist.github.com/2510570
Couple of changes. Not quite finished yet, but check out the following
Have Program extend a JFrame.
Have set a layout manager.
Update
Finally I knocked this up in IntelliJ's form designer.
https://gist.github.com/2512197
Where you want to attach behaviour to the buttons search through the code for the comments that ask you to add code. Although I did this in the InteliJ Ultimate (this one that costs money) I think that no-cost free to download Community Edition UI designer also paints Swings GUIs. Very quick and easy. Netbeans also has a good GUI painter.
The Swing Tutorial on oracle.com is worth reviewing also.
I can't .setText(...) for a JTextField outside of the class that creates the gui. I'm very confused and I feel like there is something basic I am missing. I need some help here.
Here is what I am doing:
In a class (called MainClass) I create an instance of a class that creates my gui
TestText gui = new TestText();
with a constructor that sets the default settings (a JTextField and a button with a listener). Then I call the a setter that I wrote, where I pass it a string that is to set the text of the JTextField:
gui.setText("new");
But "new" doesn't show up on the gui.
I know my setter works from within the class because if I make a call to the setter from the button that I created in gui then the changes show up on the gui.
The part that really confuses me is this: If I call my getter just before my setter, then it returns the old value. Then if I call the getter again after I call the setter then it returns the new value, while the gui continues to show the old value. I thought that maybe it just isn't repainting the gui so I tried all kinds of permutations of .invalidate(), .validate(), .update() and .repaint(), all from the MainClass and from inside the setter. But none did anything.
Is it possible that I somehow have 2 different instances of the gui and I'm only editing one of them?
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestText {
private JTextField textField;
private JButton button;
private JPanel frame;
JFrame jFrame;
public void setText(String text) {
textField.setText(text);
}
public String getText() {
return textField.getText();
}
public TestText() {
this.textField.setText("98.6");
this.jFrame = new JFrame("TestText");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setText("new (button)");
}
});
}
public void setData(TestText data) {
data.setText("new (setData)");
}
public void getData(TestText data) {
}
public boolean isModified(TestText data) {
return false;
}
public void createGui(String[] args) {
jFrame.setContentPane(new TestText().frame);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.pack();
jFrame.setVisible(true);
}
}
and then here's the main class that I'm trying to create the gui from:
public class MainClass {
public static void main(String[] args) {
TestText gui = new TestText();
gui.createGui(null);
System.out.println(gui.getText());
gui.setData(gui);
System.out.println(gui.getText());
gui.setText("new (MainClass)");
System.out.println(gui.getText());
}
}
It looks like you're missing the reference to the text field I think...
gui.referenceToTextField.setText("new word");
EDIT: Very nice SSCCE! However, there are several problems (not in the order provided, necessarily).
You are overriding the setText() method. Don't do this unless you want the method to do something different—why you would want to do this I have no idea.
You aren't even using the args array in the createGui() method. You can create methods without specifying any parameters/arguments.
The getData() method is, right now, useless (If I were you, given what you're trying to accomplish, I would remove the method entirely). I'm assuming, from the apt method name (another good thing to do), that you want to retrieve the data from the text field. Put this line inside the method (and change the word void to String) and you should be set!
return textField.getText();
Truthfully, this shouldn't even run due to a NullPointerException. You aren't initializing any of the components other than the JFrame. You need to do things like textField = new JTextField(20).
Even if you could run this, the button wouldn't work at all because the button hasn't been told that it does anything. To do this call button.addActionListener() with the name of the listening class as the argument. If the GUI and listening classes happen to be in one class together (like I will show you in a minute), the argument is simply this.
You aren't adding any components to the frame. For every component you wish to put into your frame, you must call add(Component cmpt).
Having said this, I think I'm just going to try to recreate what you're trying to do here into one class. You don't really need two separate classes unless the listening portion is excessively long.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestText extends JFrame implements ActionListener {
JTextField textField = new JTextField(20);
JButton set = new JButton("Set Text");
JButton get = new JButton("Get Text");
public TestText() {
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(textField);
set.addActionListener(this); //this tells the program that the button actually triggers an event
add(set);
get.addActionListener(this);
add(get);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == set) {
textField.setText(JOptionPane.showInputDialog(null, "Enter a new word for the text field:"));
} else {
System.out.println(textField.getText());
}
}
public static void main(String[] args) {
TestText tt = new TestText();
}
}
After doing some reading I think it is due to my code not accessing the Event Dispatch Thread like #camickr suggested. Here is some documentation that helped me solve my problem.