FocusListener on JTextField not working - java

I've created an application that uses FocusListener to make sure a text fieid's value is always positive. When the user inputs negative value and then click the "tab" key to move focus away from the text field, the value will be multiplied by -1 so that the resulted value is positive. However, when I ran the application, the text field didn't change. I am not sure what I did wrong, and will appreciate any help.
Here is my code:
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class AlwaysPositive extends JFrame implements FocusListener {
JTextField posField = new JTextField("30",5);
public AlwaysPositive() {
super("AlwaysPositive");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel pane = new JPanel();
JTextField posField = new JTextField("30",5);
JButton ok= new JButton("ok");
posField.addFocusListener(this);
pane.add(posField);
pane.add(ok);
add(pane);
setVisible(true);
}
public void focusLost(FocusEvent event) {
try {
float pos = Float.parseFloat(posField.getText());
if (pos < 0)
pos = pos*-1;
posField.setText("" + pos);
} catch (NumberFormatException nfe) {
posField.setText("0");
}
}
public void focusGained(FocusEvent event) {
}
public static void main(String[] arguments) {
AlwaysPositive ap = new AlwaysPositive();
}
}

The main problem is you are shadowing your variables
You declare
JTextField posField = new JTextField("30",5);
As an instance variable, but in your constructor, you redeclare it again...
public AlwaysPositive() {
//...
JTextField posField = new JTextField("30",5);
posField.addFocusListener(this);
//...
}
Add attach the focus listener to it, but in the focusLost method, you are referring to the instance variable, which isn't the one that is actually on the screen
Start by changing the declaration within the constructor
public AlwaysPositive() {
//...
posField = new JTextField("30",5);
posField.addFocusListener(this);
//...
}
However, there are better solutions to use then FocusListener.
For example, you could use an InputVerifier that will allow you to verify the value of the field and make decisions about whether focus should be moved or not.
Take a look at How to Use the Focus Subsystem and Validating Input in particular
You could also use a DocumentFilter to restrict what the user can actually enter, filtering the input as the user types it. Take a look at Text Component Features and Implementing a Document Filter in particular.
You can also take a look at these examples for more ideas

When you create object of same name inside a method, the listener is set to the method object and not to the Class object.

Related

Java - Linking a JTextField variable with another class variable

What I want to achieve is very simple.
I have 2 classes. "SpeedingTicket" & "SpeedingTicket GUI".
Inside my GUI I have 1 textbox name txtSpeedLimit & a button.
Inside my SpeedingTicket class I have a variable "int speedingTicket".
Inside my SpeedingTicket class I also have a get & set method for "speedingTicket".
I know how to get and set text using JTextFields, but I want to be able to:
receive input from the "txtSpeedLimit", and store that value into the "txtSpeedLimit" instance variable in the "SpeedTicket" class. I can then check for validation etc when I come to adding the vehicle speed.
Maybe this isn't the most efficient way of dealing with this program. Maybe I should scrap the instance variables in SpeedingTicket, and deal with it all in the GUI.
Any advice would be hugely appreciated.
Basically what I'm trying to do is this:
class confirmHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
String val = txtSpeedLimit.getText();
int realNum = speed.getSpeedLimit() = txtSpeedLimit; < but obviously that doesn't work, but I want the textbox link to the variable.
EDIT: If we take away the GUI, all I want my program to do is the following:
Speed Limit: 50 < enterd via textfield
Speed: 60 < entered via textfield
if the speed is blah blah (ive already coded this).. then output a result to one of my labels.
I achieved this without making a GUI and making it only console based, but instead of the user typing it via the console, I want it to be typed via textfields.
THe values that are entered into the textfields should be stored in the two variables (speed and speedlimit) that are in the SpeedingTicket class.
You can update a value in:
public class SpeedingTicket {
int speedingTicket;
public SpeedingTicket() {
speedingTicket = 500;
}
public int getSpeedingTicket() {
return speedingTicket;
}
}
by:
public class SpeedingTicketGUI extends JPanel{
SpeedingTicket st;
SpeedingTicketGUI() {
st = new SpeedingTicket();
setLayout(new FlowLayout(FlowLayout.LEFT));
JTextField txtField = new JTextField(10);
txtField.setText(""+st.getSpeedingTicket());
add(txtField);
JButton btn = new JButton("Update");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setSpeedingTicket(txtField.getText());
}
});
add(btn);
}
private void setSpeedingTicket(String text) {
try {
int speedTicket = Integer.parseInt(text);
st.setSpeedingTicket(speedTicket);
System.out.println("Speeding ticket set to " +st.getSpeedingTicket());
} catch (NumberFormatException ex) {
System.out.println("Invalid value " +text);
ex.printStackTrace();
}
}
public static void main(String[] args){
JFrame frame = new JFrame("Speeding Ticket");
frame.setSize(400,100);
frame.add(new SpeedingTicketGUI());
frame.setVisible(true);
}
}
You don't need to store values in JText or any GUI componenets...
Use global static variables. For example:
public static int speed_limit;
You can access this variable from ANY method,class, etc.
There are multiple ways to do it.
You can detect textfield changes by using a DocumentListener or if you want (not recommended) by a KeyListener.
The Listener could be implemented directly by your gui class or by your other class. If you want more abstraction you could implement the DocumentListener by your gui class and create a method
public void addSpeedChangeListener(SpeedChangeListener scl) {
this.speedChangeListeners.add(scl);
}
Your SpeedChangeListener could be very simple:
public interface SpeedChangeListener {
public void speedChanged(int value);
}
Then your second class implements the SpeedChangeListener and calls addSpeedChangeListener(this) on your gui class. Inside the gui class, your document listener calls speedChanged(val) for every listener registered.
EDIT
You can also use the Button and call the speedChanged on every listener inside the actionPerformed method of the ActionListener.
I think it would be easier to use a JOptionDialog which pop ups when the button is clicked. That way you can easily get input and also validate the input straight away.

Access GUI components from another class

I'm new to Java and I've hit a brick wall. I want to access GUI components (that have been created in one class) from another class. I am creating a new GUI class from one class, like so;
GUI gui = new GUI();
and I can access the components in that class, but when I go to a different class I cant. I really just need to access the JTextAreas to update their content. Could someone point me in the right direction please, any help is greatly appreciated.
GUI Class:
public class GUI {
JFrame frame = new JFrame("Server");
...
JTextArea textAreaClients = new JTextArea(20, 1);
JTextArea textAreaEvents = new JTextArea(8, 1);
public GUI()
{
frame.setLayout(new FlowLayout(FlowLayout.LEADING, 5, 3));
...
frame.setVisible(true);
}
}
First respect encapsulation rules. Make your fields private. Next you want to have getters for the fields you need to access.
public class GUI {
private JTextField field = new JTextField();
public GUI() {
// pass this instance of GUI to other class
SomeListener listener = new SomeListener(GUI.this);
}
public JTextField getTextField() {
return field;
}
}
Then you'll want to pass your GUI to whatever class needs to access the text field. Say an ActionListener class. Use constructor injection (or "pass reference") for the passing of the GUI class. When you do this, the GUI being referenced in the SomeListener is the same one, and you don't ever create a new one (which will not reference the same instance you need).
public class SomeListener implements ActionListener {
private GUI gui;
private JTextField field;
public SomeListener(GUI gui) {
this.gui = gui;
this.field = gui.getTextField();
}
}
Though the above may work, it may be unnecesary. First think about what exactly it is you want to do with the text field. If some some action that can be performed in the GUI class, but you just need to access something in the class to perform it, you could just implement an interface with a method that needs to perform something. Something like this
public interface Performable {
public void someMethod();
}
public class GUI implements Performable {
private JTextField field = ..
public GUI() {
SomeListener listener = new SomeListener(GUI.this);
}
#Override
public void someMethod() {
field.setText("Hello");
}
}
public class SomeListener implements ActionListener {
private Performable perf;
public SomeListener(Performable perf) {
this.perf = perf;
}
#Override
public void actionPerformed(ActionEvent e) {
perf.someMethod();
}
}
Several approaches are possible:
The identifier gui is a reference to your GUI instance. You can pass gui to whatever class needs it, as long as you respect the event dispatch thread. Add public accessor methods to GUI as required.
Declarations such as JTextArea textAreaClients have package-private accessibility. They can be referenced form other classes in the same package.
Arrange for your text areas to receive events from another class using a PropertyChangeListener, as shown here.
The best option to access that text areas is creating a get method for them. Something like this:
public JTextArea getTextAreaClients(){
return this.textAreaClients;
}
And the same for the other one.So to access it from another class:
GUI gui = new GUI();
gui.getTextAreaClients();
Anyway you will need a reference for the gui object at any class in which you want to use it, or a reference of an object from the class in which you create it.
EDIT ---------------------------------------
To get the text area from GUI to Server you could do something like this inside of Create-Server.
GUI gui = new GUI();
Server server = new Server();
server.setTextAreaClients(gui.getTextAreaClients());
For this you should include a JTextArea field inside of Server and the setTextAreaClients method that will look like this:
JTextArea clients;
public void setTextAreaClients(JTextArea clients){
this.clients = clients;
}
So in this way you will have a reference to the JTextArea from gui.
here i add a simple solution hope it works good,
Form A
controls
Textfield : txtusername
FormB fb = new FormB();
fb.loginreset(txtusername); //only textfield name no other attributes
Form B
to access FormA's control
public void ResetTextbox(JTextField jf)
{
jf.setText(null); // or you can set or get any text
}
There is actually no need to use a class that implements ActionListener.
It works without, what might be easier to implement:
public class SomeActionListener {
private Gui gui;
private JButton button1;
public SomeActionListener(Gui gui){
this.gui = gui;
this.button1 = gui.getButton();
this.button1.addActionListener(l -> System.out.println("one"));
}
}
and then, like others have elaborated before me in this topic:
public class GUI {
private JButton button = new JButton();
public GUI() {
// pass this instance of GUI to other class
SomeActionListener listener = new SomeActionListener(GUI.this);
}
public JButton getButton() {
return button;
}
}

Document Listener java "Cannot instantiate the type DocumentListener"

I'm trying to write a simple retirement calculator for a project.
I'm trying to get a document listener so I can take input from different text fields and use them in my calculations.
For some reason I can't get the DocumentListener to instantiate, and I get an error. I think that I lack understanding of how to do this.
The specific line of code that is giving me an error is this:
DocumentListener DL = new DocumentListener();
Here is the class where I try to use this:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class TextFields extends JPanel implements DocumentListener
{
public TextFields()
{
setLayout(new GridLayout(5,1));
setFont(new Font("Tahoma", Font.PLAIN, 14));
DocumentListener DL = new DocumentListener();
JTextField age = new JTextField("Age");
age.getDocument().addDocumentListener(DL);
JLabel ageLabel = new JLabel("Age: ");
JTextField initialSavings = new JTextField("Intial Savings");
JLabel ISLabel = new JLabel("Inital Savings: ");
JTextField ageRetire = new JTextField("Retirement Age");
JLabel RALabel = new JLabel("Retirement Age: ");
JTextField inflation = new JTextField("Inflation Rate");
JLabel inflationLabel = new JLabel("Inflation Rate: ");
JTextField dailySavings = new JTextField("Daily Savings");
JLabel DSLabel = new JLabel("Daily Savings: ");
JTextField DeathAge = new JTextField("Age Of Death");
JLabel DALabel = new JLabel("When will you die? ");
JTextField retirementIncome = new JTextField("Retirement Income:");
JLabel RILabel = new JLabel("Retirement Income: ");
JTextField interest = new JTextField("Interest Rate");
JLabel interestLabel = new JLabel("Interest: ");
add(ageLabel);
add(age);
add(ISLabel);
add(initialSavings);
add(RALabel);
add(ageRetire);
add(inflationLabel);
add(inflation);
add(DSLabel);
add(dailySavings);
add(DALabel);
add(DeathAge);
add(interestLabel);
add(interest);
add(RILabel);
add(retirementIncome);
}
#Override
public void changedUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void insertUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void removeUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
}
}
Since I am beginning programer, I would appreciate simple answers that won't require a huge amount knowledge to understand.
Thank you very much for your time and help!
Roy.
Short version:
...
// DocumentListener DL = new DocumentListener();
JTextField age = new JTextField("Age");
age.getDocument().addDocumentListener(this);
...
Long version:
First, I'm going to give you the error explanation. After that, I'm including a particular case suitable for your needs.
That error means that your DocumentListener is either an abstract class, or an interface (read about these two, then you'll get the idea).
The solution is either to look for subclasses of it (press CTRL + T while the class name is selected in the Eclipse IDE editor) OR to create an anonymous class right where you're instantiating it (see example below). Keep in mind that instantiating interfaces is generally not a good idea (not unless you know what you're doing), i.e. interfaces should be implemented by separate classes, and then instantiate THOSE classes.
DocumentListener dl = new DocumentListener()
{
// implement abstract methods here
};
Knowing this, we now have to particularise all of this to your code.
When attaching listeners to different elements (usually, listeners are interfaces), the code standard is to add the listener as an anonymous class directly as the API parameter, like so:
age.getDocument().addDocumentListener(new DocumentListener()
{
// implement necessary methods here
});
A quick Google Search instantly tells me what methods you need to implement there. Finally, your code should look like:
age.getDocument().addDocumentListener(new DocumentListener()
{
public void changedUpdate(DocumentEvent e)
{
}
public void insertUpdate(DocumentEvent e)
{
}
public void removeUpdate(DocumentEvent e)
{
}
});
Inside these methods, you may do whatever you want with those receiving events (of type DocumentEvent - read the javadoc)
ANOTHER way to do it (the way that you've already started doing), is to implement the DocumentListener directly in your working class, and then implement those methods there (as you did - notice the three overridden methods at the end of your class). In this case, all you have to do is tell the age.getDocument() where it can find the listener.
age.getDocument().addDocumentListener(this);
By writing this as listener, it means that when DocumentEvents are thrown, the execution will pass through those methods of yours there (changedUpdate, insertUpdate, removeUpdate).
As you can see in your TextFields class declaration you are implementing DocumentLstener which means that's an interface and you can't instantiate an interface.
replace the problematic line with this
DocumentListener DL = new TextFields();
Since TextFields has implemented the DocumentListener interface everything will be fine.
Or you can use a separate or inner class for listener.

Calling String from another method - Java

I am trying to use this String called "username" from another method, but I can't seem to figure out what to do.
I have this bit of code right here, which assigns a text field's entry to a variable, but I can't seem to use this variable in another method
//Configuring content pane
JFormattedTextField formattedTextField = new JFormattedTextField();
formattedTextField.setBounds(129, 36, 120, 20);
UsernameFrame.getContentPane().add(formattedTextField);
UsernameFrame.setVisible(true);
//Assigning text field entry to variable
String username = formattedTextField.getText();
Now, I am trying to use this variable in the method pasted below, but I don't know what I am missing..
public void actionPerformed(ActionEvent e){
if(username.length() < 5){
}
//Execute when the button is pressed
System.out.println("The button has been pressed");
}
This is probably something really simple I am missing, thanks for your help guys.
(full code)
http://pastebin.com/RMszazd4
Declare username right after your class declaration like this:
public class App {
private String username;
public static void main(String[] args) {
...
}
...
}
If these are two separate methods you will need to reassign the username variable again or you can create a global variable outside of your methods.
You might want to pass in the string variable "username"as a parameter to another method since it would not recognize the scope of your string in another method unless its declared global.
You don't appear to have a way of reading the JFormattedTextField. If I understand what you're trying to do correctly, you could declare formattedTextField as an instance variable, and then declare username inside the listener:
public class Frame {
JFrame UsernameFrame = new JFrame("Welcome");
private JFormattedTextField formattedTextField;
....
btnSubmit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String username = formattedTextField.getText();
if (username.length() < 5) {
}
// Execute when the button is pressed
System.out.println("The button has been pressed");
}
});
Now you have a reference to the text of the JFormattedTextField to do what you will with each time the button is pressed.

updating Swing JTextField

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.

Categories