简体   繁体   中英

What's wrong with my code?

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");  
    }
}

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.

ie, 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.

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 .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM