-1

This code is compiling and executing too, but the method actionPerformed() is not executing properly. I mean after clicking on the OK Button, there is nothing written in the JTextField. NO action is performed even after using e.getSource(). The System.out.println("I am done ") is working properly, but t.setText("Hey there") is not working.? What is wrong with the code?? Please help me if anyone can.
And also can you elaborate me why if not adding JButton and JTextField on Panel it is not visible? Why it is important to add panel in order to make button and text field visible. Without it is not visible why?

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class A implements ActionListener {

    JFrame f;
    JButton b;
    JPanel p;
    JLabel l;
    JTextField t;

    A(String s) {
        JFrame f=new JFrame(s);
        f.setVisible(true);
        f.setSize(400,400);
        JButton b= new JButton("OK");
        JTextField t=new JTextField();
        JPanel p=new JPanel(); 
        f.add(p);
        p.setBounds(0,0,300,300);
        p.add(b);
        b.setBounds(30,40,80,80);
        p.add(t);
        t.setBounds(100,200,80,80);
        b.addActionListener(this);
        t.addActionListener(this);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == b) {    
            t.setText("Hey There");
        }
        System.out.println("I m done!!");
    }

    public static void main(String[] args) {
         System.out.println("Hey there");  
         new A("First App");  
    }
}
Violet
  • 47
  • 12
  • *"And also can you.."* A question on SO should be a single, specific question. Other questions are better started on separate threads. Also: Use a logical and consistent form of indenting code lines and blocks. The indentation is intended to make the flow of the code easier to follow! – Andrew Thompson Jun 21 '15 at 19:11
  • Note also that your question title is not helpful for us since it is singularly non-informative. "What's wrong with my code" tells us **nothing** about your problem, other than you're having a problem -- but we already knew that, else you wouldn't be here. In the future, please work on asking better questions with better titles. This will help both you and us. – Hovercraft Full Of Eels Jun 21 '15 at 19:12
  • 2
    `f.setVisible(true);` should be last, after `pack()`. And `p.setBounds(0, 0, 300, 300);` Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Jun 21 '15 at 19:13

3 Answers3

3

You're shadowing the b variable by re-declaring it in your constructor meaning that the b field in the class is not the same that is displayed in your GUI. Don't do this and your problem is solved.

i.e., you're doing this:

class A {
   JButton b; // this guy stays null!

   public A() {
       JButton b = new JButton(...);
   }

The solution is to do this:

class A {
   JButton b;

   public A() {
       b = new JButton(...); //note the difference?
   }

You ask:

And why it is important to add panel in order to make button and text field visible in swing?

It's a matter of layout manager. A JPanel by default uses a FlowLayout which will allow you to add components like filling out books in a book shelf from the top left. A JFrame's contentPane on the other hand uses a BorderLayout, and if you add things by default to this, only the last thing added will show and will fill the GUI. Note that you're trying to setBounds(...) and you shouldn't be doing this. Let the layout managers do there thing.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
3

You're shadowing all of the fields in your constructor.

Remove the redeclarations and it will work as expected.

Something like this:

A(String s) {
    f = new JFrame(s);
    f.setVisible(true);
    f.setSize(400, 400);
    b = new JButton("OK");
    t = new JTextField();
    p = new JPanel();
    f.add(p);
    p.setBounds(0, 0, 300, 300);
    p.add(b);
    b.setBounds(30, 40, 80, 80);
    p.add(t);
    t.setBounds(100, 200, 80, 80);
    b.addActionListener(this);
    t.addActionListener(this);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

Notice that we don't redeclare any of those variables. This is why your event isn't firing; the declared field is still null.

Makoto
  • 104,088
  • 27
  • 192
  • 230
3

Instead of doing what you are doing why don't you use anonymous inner class?

Something like:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

class A {
    JFrame f;
    JButton b;
    JPanel p;
    JLabel l;
    JTextField t;

    A(String s) {
        f = new JFrame(s);
        f.setVisible(true);
        f.setSize(400, 400);

        p = new JPanel();
        p.setBounds(0, 0, 300, 300);

        t = new JTextField();
        t.setBounds(100, 200, 80, 80);
        p.add(t);

        b = new JButton("OK");
        b.setBounds(30, 40, 80, 80);
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                t.setText("Hello! World.");
            }
        });
        p.add(b);
        f.add(p);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        System.out.println("Hey there");
        new A("First App");
    }
}

I did not execute this code but I am sure this is gonna work and this approach would help you organize your code better. This is how I generally code.

If you are using Java 8 then use of lambda expressions would be the best idea as the ActionListener is a Single Abstract Method Interface.

If you want to look at the use then this is how it is:

b.addActionListener(e -> t.setText("Hello! World."));

for better understanding you can have a look at this video. It is for JavaFX but the concepts of anonymous inner classes and lambda expressions remain the same.

anonymous inner classes and lambda expressions

Tom
  • 16,842
  • 17
  • 45
  • 54