Problems with getText() from JTextField - java

I'm having troubles with the .getText() command trying to retrieve data from a JTextField. I've been looking for the solution but couldn't find it. Is there anybody who can see what I'm doing wrong?
What I'm trying is to make is a bouncing ball which parameters such as elasticity, gravity and initial speed can be changed.
When trying to compile the following message appears:
ERROR in BBPanel.java (at line 88) String gravityIn = gravity_input.getText();
gravity_input cannot be resolved
Thanks!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/////////////////////////////////////////////////////////////////// BBPanel
class BBPanel extends JPanel {
BallInBox n_bb; // The bouncing ball panel
//========================================================== constructor
/** Creates a panel with the controls and bouncing ball display. */
BBPanel() {
//... Create components
n_bb = new BallInBox();
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
JButton resetButton = new JButton("Reset");
JButton gveButton = new JButton("GetData");
JLabel gravityLbl = new JLabel (" set gravity " );
JLabel velocity_yLbl = new JLabel (" set initial y-dir speed " );
JLabel elasticityLbl = new JLabel (" set elasticity [0-100%]" );
JTextField gravity_input = new JTextField(20);
JTextField velocity_y_input = new JTextField(20);
JTextField elasticity_input = new JTextField(20);
//... Add Listeners
startButton.addActionListener(new StartAction() );
stopButton.addActionListener(new StopAction() );
resetButton.addActionListener(new ResetAction() );
gveButton.addActionListener(new DataAction() );
//... Layout inner panel with three buttons horizontally
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(startButton);
buttonPanel.add(stopButton);
buttonPanel.add(resetButton);
//
JPanel variablePanel = new JPanel();
variablePanel.setLayout(new GridLayout(0,2));
variablePanel.add(gravityLbl);
variablePanel.add(gravity_input);
variablePanel.add(velocity_yLbl);
variablePanel.add(velocity_y_input);
variablePanel.add(elasticityLbl);
variablePanel.add(elasticity_input);
variablePanel.add(gveButton);
//... Layout outer panel with button panel above bouncing ball
this.setLayout(new BorderLayout());
this.add(buttonPanel , BorderLayout.NORTH);
this.add(n_bb , BorderLayout.CENTER);
this.add(variablePanel, BorderLayout.EAST);
}//end constructor
////////////////////////////////////// inner listener class StartAction
class StartAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.setAnimation(true);
}
}
//////////////////////////////////////// inner listener class StopAction
class StopAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.setAnimation(false);
}
}
///////////////////////////////////////// inner listener class ResetAction
class ResetAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.resetAnimation(true);
}
}
////////////////////////////////////////// inner listener class GravityAction
class DataAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String gravityIn = gravity_input.getText();
//System.out.println(gravityIn);
n_bb.setData(true);
}
}
}//endclass BBPanel

The variable gravity_input is only defined locally in the scope of the constructor of BBPanel. You need to make it a class member variable if you wish to make it visible to your DataAction class.
public class BBPanel extends JPanel {
private JTextField gravity_input; // to be initialized...
...
Side note:
Java uses camel-case which would make gravity_input gravityInput.

Your problem is one of scope. The gravity_input is declared inside of a constructor or method. To be visible outside of these blocks, it should be declared in the class similar to how you declare the n_bb field.

Your variable gravity_input should be declared as an instance variable (outside the constructor), for it to be later accessed.
The way you're defining it, the name (not the text field) gravity_input dies as soon as the constructor code terminates (reaches closing brace }).

pass parameters as follows into constructor of DataAction:
class DataAction implements ActionListener {
final JTextField textField;
final BallInBox bb;
public DataAction(final JTextField textField, final BallInBox bb) {
this.textField = textField;
this.bb = bb;
}
public void actionPerformed(ActionEvent e) {
String gravityIn = textField.getText();
//System.out.println(gravityIn);
bb.setData(true);
}
}
and use it like this:
gveButton.addActionListener(new DataAction(gravity_input, n_bb));
Then refactor your other actions in a similar way.

The problem is, that your class DataAction doesn't know about your gravity_input textfield.
The textfield gravity_input is only visible to the class BBPanel. To make it visible to the class DataAction, you have to pass the textfield to that class like this:
class DataAction implements ActionListener {
private JTextField gravity_input;
public DataAction(JTextField txtField) {
gravity_input = txtField;
}
public void actionPerformed(ActionEvent e) {
String gravityIn = gravity_input.getText();
//System.out.println(gravityIn);
n_bb.setData(true);
}
}
and change your BBPanel constructor to this:
BBPanel() {
//... omitted
gveButton.addActionListener(new DataAction(gravity_input));
//... omitted
}

Related

Adding ActionListener to JButtons

When attempting to implement ActionListener I receive the following error
EmployeesApplet.java:5: error: EmployeesApplet is not abstract and does not override
abstract method actionPerformed(ActionEvent) in ActionListener
public class EmployeesApplet extends JApplet implements ActionListener
^
1 error
I do not want to make EmployeesApplet abstract since it doesn't need to be.
My code is below, note I commented out the implements ActionListener and adding the JButtons as ActionListener
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class EmployeesApplet extends JApplet //implements ActionListener
{
public JButton sd = new JButton ("Salaried");
public JButton hr = new JButton ("Hourly");
public JButton cm = new JButton ("Commissioned");
public JButton cl = new JButton ("Clear");
private final int FIELDS = 8,
FIELD_WIDTH = 20;
private String[] strings = new String[FIELDS];
private TextFieldWithLabel[] tf = new TextFieldWithLabel[FIELDS];
private JTextArea ta = new JTextArea(5,25);
public void init()
{
String[] s = {"First Name", "Last Name", "Employee ID", "(a) Salaried: Weekly Salary", "(b1) Hourly 1: Rate Per Hour",
"(b2) Hourly 2: Hours Worked" , "(c1) Commissioned: Rate", "(c2) Commissioned: Gross Sales" };
//----------------------
// Set up the Structure
//----------------------
Container c = getContentPane();
JPanel f = new JPanel(new FlowLayout());
JPanel b = new JPanel(new BorderLayout(2,0));
JPanel glb = new JPanel(new GridLayout(8,1,0,2));
JPanel gtf = new JPanel(new GridLayout(8,1,0,2));
JPanel flb = new JPanel(new FlowLayout());
// Add FlowLayout to the container
c.add(f);
// Add BorderLayout to the FlowLayout
f.add(b);
//---------------------------------------
//Add JPanels to the BorderLayout regions
//---------------------------------------
// Add JLables to GridLayout in West
b.add(glb, BorderLayout.WEST);
for (int i = 0; i < tf.length; i++)
{
tf[i] = new TextFieldWithLabel(s[i], FIELD_WIDTH);
glb.add(tf[i].getLabel());
}
// Add JTextFeilds to GridLayout in East
b.add(gtf, BorderLayout.EAST);
for (int i = 0; i < tf.length; i++)
{
tf[i] = new TextFieldWithLabel(s[i], FIELD_WIDTH);
tf[i].getTextField();
gtf.add(tf[i].getTextField());
}
// Add JButtons to FlowLayout in South
b.add(flb, BorderLayout.SOUTH);
flb.add(sd);
flb.add(hr);
flb.add(cm);
flb.add(cl);
//sd.addActionListener(this);
//hr.addActionListener(this);
//cm.addActionListener(this);
//cl.addActionListener(this);
// Add JTextArea and make it not editable
f.add(ta);
ta.setEditable(false);
}
public void readFields()
{
}
public void fieldsExist()
{
}
public void fieldsEmpty()
{
}
public void actionPerformed()
{
}
}
Your actionPerformed method needs an ActionEvent as it's parameter:
public void actionPerformed(ActionEvent e) {
}
Otherwise you won't be overriding the method defined in ActionListener - you'll just be creating a new method. Since ActionListener is an interface, you are required to implement all the methods defined in the interface, hence the error.
The actionPerformed method is declared with the ActionEvent parameter to pass the method details about the event (which component triggered the event, the action command, etc..). Without the ActionEvent parameter, there is no easy way to gather such information. When an action is performed, an ActionEvent object is created, filled with the event information, then your actionPerformed method is invoked, which the ActionEvent object is passed in as an argument.
Your class is implementing the interface ActionListener
hence you have 2 options... make the class abstract or implement the method actionPerformed
the first one looks like what you need....
so try doing something like:
public class EmployeesApplet extends JApplet implements ActionListener {
....
....
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}

Exiting JFrame when JButton is clicked

I am writing a Login GUI and want the cancel button to close the entire program when clicked. I'm a freshman computer science major and still semi-new to java and programming in general. Here is my code:
Main Class:
public class loginGui
{
public static void main(String[] args)
{
lGui gui = new lGui();
lGui.gui();
}
}
GUI class:
public class lGui
{
public static void gui()
{
JFrame frame;
JTextField field;
JLabel l;
JPasswordField p;
JButton login, cancel;
JCheckBox check;
frame = new JFrame("Login");
frame.setSize(300, 150);
frame.getContentPane().setBackground(Color.LIGHT_GRAY);
frame.setLocation(300, 200);
frame.setLayout(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
l = new JLabel("Username: ");
l.setLocation(15, 14);
l.setSize(l.getPreferredSize());
frame.add(l);
field = new JTextField("Username");
field.setColumns(15);
field.setSize(field.getPreferredSize());
field.setBackground(Color.DARK_GRAY);
field.setForeground(Color.LIGHT_GRAY);
field.setLocation(90, 10);
field.setToolTipText("Enter User Name");
frame.add(field);
l = new JLabel("Password: ");
l.setLocation(15, 54);
l.setSize(l.getPreferredSize());
frame.add(l);
p = new JPasswordField("Password");
p.setColumns(15);
p.setSize(p.getPreferredSize());
p.setBackground(Color.DARK_GRAY);
p.setForeground(Color.LIGHT_GRAY);
p.setLocation(90, 50);
p.setToolTipText("Enter Password");
frame.add(p);
login = new JButton("Login");
login.setSize(login.getPreferredSize());
login.setLocation(195, 78);
login.setToolTipText("Login");
frame.add(login);
login.addActionListener(new loginAction());
cancel = new JButton("Cancel");
cancel.setSize(cancel.getPreferredSize());
cancel.setLocation(95, 78);
cancel.setToolTipText("Cancel");
frame.add(cancel);
cancel.addActionListener(new cancelAction());
check = new JCheckBox("Remember me?");
check.setSize(check.getPreferredSize());
check.setLocation(120, 100);
check.setToolTipText("Remember your username for next time");
frame.add(check);
frame.setVisible(true);
}
static class cancelAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
frame.dispose();
}
}
static class loginAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
}
}
}
I keep getting a "cannot find symbol" error here in the cancel button ActionListener:
frame.dispose();
frame only has context from within your static method gui. Start by getting rid of the static declaration and make frame an instance field of the class
public class lGui
{
private JFrame frame;
private JTextField field;
private JLabel l;
private JPasswordField p;
private JButton login, cancel;
private JCheckBox check;
public void gui()
{
//...
You also won't need the static declarations on the inner classes...
protected class cancelAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
frame.dispose();
}
}
protected class loginAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
}
}
You might find it easier to make initialise the UI from within the classes constructor instead of the gui method, leaving it to show the window
You should also avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
Instead, have a look at Laying Out Components Within a Container for some more ideas
The code in gui method has to be in a constructor and your JFrame object has to be defined outside of any methods, as a field of the class :)

Recalling JButton value

I'm looking to recall a JButton's value when clicked i.e. when the user clicks a JButton, the value of that JButton (which is a single letter) will be written to a JLabel. The user will click multiple buttons and as such, multiple values will need to be stored and printed. Finally the user will click a button and the JLabel holding all recieved JButton values will be stored (Obviously using an array).
Here is what my JButton's look like in code:
theModel.randomLetters();
for(int i=0;i<16;i++){
JButton dice = new JButton(theModel.letters.get(i));
dice.addActionListener(disableButtonListener);
boggleGrid.add(dice);
}
theModel.randomLetters(); is a reference to another class with "letters" being an array holding 16 values. Will I need to add each JButton individually to the boggleGrid so their individual names can be recalled to achieve the goal stated above, or do they have individual names and I don't know it? (I've used a for loop someone gave me so I'm not sure if there are individual names for each JButton)
Thanks, and sorry if this is elementary
Read the following code, you'll get some ideas...
I used a StringBuilder to store the values of the Button's each time they were clicked by using StringBuilder.append(JButton.getText().toString()). That was done in the actionPerformed methods of the JButtons.
Then finally in the Done buttons actionPerformed method I had stored the text the string builder held in an array.
P.S. I know you're using 16 JButton's I just used 3 for simplicity...
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.ArrayList;
public class GUI extends JFrame{
ArrayList<String> numbers = new ArrayList<>();
StringBuilder sb = new StringBuilder();
JButton button1;
JButton button2;
JButton button3;
JButton doneButton;
JPanel row1 = new JPanel();
JPanel textLabelRow = new JPanel();
JLabel label = new JLabel();
JPanel row3 = new JPanel();
public void create(){
setTitle("S-O");
setSize(500,200);
setLayout(new GridLayout(3,1,10,10));
button1 = new JButton("1");
button2 = new JButton("2");
button3 = new JButton("3");
doneButton = new JButton("Done");
row1.add(button1);
row1.add(button2);
row1.add(button3);
button1.addActionListener(new Button1Listener());
button2.addActionListener(new Button2Listener());
button3.addActionListener(new Button3Listener());
doneButton.addActionListener(new doneButtonListener());
textLabelRow.add(label);
row3.add(doneButton);
add(row1);
add(textLabelRow);
add(row3);
setVisible(true);
}
private class Button1Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sb.append(button1.getText().toString());
}
}
private class Button2Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sb.append(button2.getText().toString());
}
}
private class Button3Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sb.append(button3.getText().toString());
}
}
private class doneButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
label.setText(sb.toString());
numbers.add(sb.toString());
sb = new StringBuilder();
}
}
public static void main(String[] args){
GUI start = new GUI();
start.create();
}
}
EDIT:
You could just use one class which implements ActionListener opposed to having one for each JButton.
With in the actionPerformed method "public void actionPerformed(ActionEvent ev)"
You would have to ev.getActionCommand(), that would return the text value of the JButton which caused the event. Then you could append that to the StringBuilder.
So something along the lines of this:
private ArrayList listForEdit = new ArrayList<>();
StringBuilder sbEdit = new StringBuilder();
class actionHandler implements ActionListener{
public void actionPerformed(ActionEvent ev){
if(ev.getActionCommand.equals("Done"))
listForEdit.add(sbEdit);
sbEdit = new StringBuilder();
}
else{
sbEdit.append(ev.getActionCommand());
}
}

Fetch TextField value by pressing Jbutton

Here is the problem:
I want an interactive GUI that has a TextField and a JButton. Users enter their pincode in TextField, press the JButton and the value fetches from main class to use as an argument in a function.
This is my JFrame with TextField and Button code:
public class JTextFieldDemo extends JFrame {
//Class Declarations
JTextField jtfText1, jtfUneditableText;
String disp = "";
ButtonHandler handler = null;
String pin;
//Constructor
public JTextFieldDemo() {
super("Smart Token Utility");
Container container = getContentPane();
container.setLayout(new FlowLayout());
jtfText1 = new JTextField(10);
jtfUneditableText = new JTextField("Please Enter Your PIN Code", 20);
jtfUneditableText.setEditable(false);
container.add(jtfText1);
container.add(jtfUneditableText);
handler = new ButtonHandler();
JButton button = new JButton("Enter");
button.setSize(3,5);
button.addActionListener(handler);
container.add(button);
setSize(325, 100);
setLocationRelativeTo(null);
setVisible(true);
jtfText1.addActionListener(handler);
}
//Inner Class ButtonHandler
private class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
pin = jtfText1.getText();
}
}
and This is my main class code:
public static void main(String args[]) {
JTextFieldDemo test = new JTextFieldDemo();
String pincode = test.pin;
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
KeyStore.load(null, pincode);
}
I have two problems:
1) When I run the main class, the Jframe appears and before I can type anything in TextField it disappears.
2) The pincode in the main class is always null even if I hardcoded it in ButtonHandler class.
As your main method get the pin code after creation of the JFrame, it will have the default value-null. So Getting the pin code(KeyStore.load(null, pincode)) method should be in ButtonHandler#actionPerformed().
But in your case you can use JOptionPane#showInputDialog(java.lang.Object, java.lang.Object) to get the input.

How can I reach swing elements from a listener?

I am currently learning how to use ActionListeners and I have a few questions about how it should be done.
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(0,1));
frame.setSize(250,250);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0,1));
final JTextField text1 = new JTextField(" ",10);
final JTextField text2 = new JTextField(" ",10);
final JTextField text3 = new JTextField(" ",10);
final JTextField text4 = new JTextField(" ",10);
panel.add(text1);
panel.add(text2);
panel.add(text3);
panel.add(text4);
ActionListener a = new ActionListener(){
public void actionPerformed(ActionEvent e){
text4.setText(text1.getText()+""+text2.getText()+""+text3.getText());
}
};
JButton buton = new JButton("Go");
buton.addActionListener(a);
frame.add(panel);
frame.add(buton);
frame.revalidate();
}
Given the code in the example, that is the only method I use inside my main class. As you can see for the listeners I am currently using some anonymous listeners that are implemented inside my main(). The thing is... I use them because clicking a button in the frame actually needs to change the content of another element.
My question is : Can you make the listener non-anonymous while still being able to use the other components? What I am thinking is moving the ActionListener implementation for the button in another class, but then how do I reach the properties of the other elements?
Example :
class listener implements ActionListener{
public void actionPerformed(ActionEvent e){
text4.setText(text1.getText()+""+text2.getText()+""+text3.getText());
}
}
then in my main() class I want to simply call :
listener l = new listener();
buton.addActionListener();
And still be able to make this outside listener acces properties of the elements inside the main class.
Yes, you can. But you'll need to explicitely pass the components to the listener, instead of passing them implicitely to the anonyous class:
class MyListener implements ActionListener {
private JTextField text1;
private JTextField text2;
private JTextField text3;
private JTextField text4;
public MyListener(JTextField text1, JTextField text2, JTextField text3, JTextField text4) {
this.text1 = text1;
this.text2 = text2;
this.text3 = text3;
this.text4 = text4;
}
#Override
public void actionPerformed(ActionEvent e){
text4.setText(text1.getText()+""+text2.getText()+""+text3.getText());
}
}
And in the main method:
button.addActionListener(new MyActionListener(text1, text2, text3, text4);
Usually though, components are stored in instance variables of an object (subclass of JPanel, typically), and listeners are implemented as inner classes (anonymous or not) that can thus access the instance variables directly:
public class MyPanel extends JPanel {
private JTextField textField;
private JButton button;
public MyPanel() {
// ...
button.addActionListener(new MyActionListener());
}
private class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(textField.getText());
}
}
}
Also, note that:
you should not access swing components from the main thread. Only from the EDT. Read the swing concurrency tutorial.
you should call pack() and setVisible() after the components have been added. revalidate() is useless in this case. Don't call setSize(). It's the role of the layout manager and of the pack() method to find the appropriate dimension of the frame.

Categories

Resources