Where would I implement the following code? By where I mean do I make a new class? Put it in the constructor of my main class? etc.
public interface ActionListener extends EventListener {
void actionPerformed(ActionEvent e);
}
You need to make a class that implements the interface.
public class ActionListenerExample implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Do something here
}
}
You can then make an object of the class.
ActionListenerExample listener = new ActionListenerExample();
With Java 8, you could make this more compact by using a lambda expression.
ActionListener listener = action -> {
// Do something
};
If you don't use Java 8 (which you should) but still want to make it compact, use an anonymous class.
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Do something here
}
}
Here's an example implemented as a local variable:
final ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello World");
}};
Related
I got this code but when I run it the actionListener is not working.
Code
public class MenuPrincipal extends javax.swing.JFrame implements ActionListener {
public MenuPrincipal() {
initComponents();
this.setVisible(true);
this.setLocationRelativeTo(null);
this.addListener();
this.jButton1 = new JButton();
this.jButton2 = new JButton();
}
public static void main(String args[]) {
new MenuPrincipal();
}
private void addListener() {
this.jButton1.addActionListener(this);
this.jButton2.addActionListener(this);
JOptionPane.showMessageDialog(null, "Activado");
}
#Override
public void actionPerformed(ActionEvent event) {
if(event.getSource().equals(this.JButton1){
// do something
}
if(event.getSource().equals(this.JButton2){
// do something
}
}
}
I'm using Netbeans to make the interface, thus I'm not pasting here the generated code.
You should write something in the method of the handler:
#Override
public void actionPerformed(ActionEvent event) {
System.out.println("button pressed!");
}
and your class should implement the ActionListener interface
Alternatively you can use the java8 lambdas:
btn.addActionListener(e -> {System.out.println("button pressed!)});
remove this 2 lines from the constructor
this.jButton1 = new JButton();
this.jButton2 = new JButton();
Since addLsiteners method didnt throw any exception, that means you have already instantiated those JButtons. if you re instantiated then those fields will have the reference to different instances than the instance you added the action listener .
So I'm trying to pass the current class inside a constructor of an actionlistner
something like this:
public ActionListener createTaskListener() {
return new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
CreateTask ct = new CreateTask();
CreateTaskController ctc = new CreateTaskController(ct, mod.getAssessments(), this);
// but it says anonymous actionlistener
ctc.loadDataToTaskView();
ct.setVisible(true);
}
};
}
What is the general approach for a problem like this? Or is this just shoddy code?
this will point to the anonymous instance of the action listener. If you want to pass the this pointer of the enclosing class, use <enclosingClassName>.this.
e.g.:
class MyClass {
public ActionListener createTaskListener() {
return new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
...
CreateTaskController ctc =
new CreateTaskController(ct, mod.getAssessments(), MyClass.this); // <-
...
}
};
}
}
As a side note. ActionListener is a functional interface. So you could simplify your code with a lambda expression:
class MyClass {
public ActionListener createTaskListener() {
return ae -> {
CreateTask ct = new CreateTask();
CreateTaskController ctc =
new CreateTaskController(ct, mod.getAssessments(), MyClass.this);
ctc.loadDataToTaskView();
ct.setVisible(true);
};
}
}
this within an inner class refers to the inner class instance. To refer to the enclosing class instance, you can use OuterclassName.this.
For example
public ActionListener createTaskListener() {
return new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
CreateTask ct = new CreateTask();
CreateTaskController ctc = new CreateTaskController(ct, mod.getAssessments(), YourClassName.this);
// but it says anonymous actionlistener
ctc.loadDataToTaskView();
ct.setVisible(true);
}
};
}
I am trying to find the answer but I can't. In java, when I create a subclass, how can I reffer the first level class? Using "this" accesses the subclass so I can't. The other option is passing the argument to the subclass but I'm curious if there is a simpliest method.
//here there is my other 1st level class implementation, this is a JFrame
btnNewProject.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
VehicleScreen pp=new VehicleScreen(**here should go the top class reference**);
//v is a JPanel that I pass to allJframes
v.setContentPane(pp);
v.setVisible(true);
}
});
class Foo {
int x;
Foo() {
new Runnable() {
public void run() {
Foo.this.x = 1;
}
}
}
}
You have a couple choices:
Make the variable outside the anonymous class an instance variable:
public class AnonymousClass extends JFrame {
private JLabel label;
...
public AnonymousClass() {
...
btnOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(textField.getText());
}
});
...
}
You can also access the instance variable as follows:
AnonymousClass.this.label.setText(textField.getText());
Use the final modifier on the local variable:
public class AnonymousClass extends JFrame {
...
public AnonymousClass() {
final JLabel label = new JLabel("Enter a new message!");
btnOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(textField.getText());
}
});
...
}
Be aware that using the final modifier will mean you cannot re-assign the variable at a later point in your program.
I just started getting my head around Java itself and Java Swing and I have some problems understanding the "Action Listener" concept. People say that C# and Java is very alike, but that's another story when you actually try out both of them and compare.
I have the following auto-generated Action Listener for a button:
btnNewButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
lblNylabel.setText("New label text");
}
});
I understand it like this:
You call a non-static method via the object "btnNewButton" btnNewButton.addActionListener()
The method takes one ActionListener instance as an argument
The automated code instansiates an ActionListener instance via the "new ActionListener()" constructor call - What I don't understand is that I can't instansiate the ActionListener class myself, but it's possible as an argument in the method call??
A "actionPerformed" method is generated inside the new instance body and used here (What?)
Inside the "actionPerformed" method you define what to do, when the button is clicked - Makes perfectly sense
Is it possible to do this in a more understanding/simple way that could help me understand the ActionListener concept?
What I don't understand is that I can't instansiate the ActionListener class myself, but it's possible as an argument in the method call??
When you do
new ActionListener() {
public void actionPerformed(ActionEvent e) {
lblNylabel.setText("New label text");
}
}
You're actually creating an instance of an anonymous subclass of ActionListener.
It is semantically equivalent of doing
class AnonymousActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
lblNylabel.setText("New label text");
}
}
btnNewButton.addActionListener(new AnonymousActionListener());
(And tada, as a bonus, you just learned that you can have method local classes in Java ;-)
Here are a few common alternatives:
Use an separate ordinary class:
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
lblNylabel.setText("New label text");
}
}
class YourClass {
public void yourMethod() {
...
btnNewButton.addActionListener(new MyActionListener());
}
}
(only possible if the other class has access to the required variables.)
Same as above, but with an inner (non-static) class:
class YourClass {
public void yourMethod() {
...
btnNewButton.addActionListener(new MyActionListener());
}
// Inner class
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
lblNylabel.setText("New label text");
}
}
}
(Here lblNylabel will probably be in scope for the inner class.)
Let the enclosing class itself implement the ActionListener and use this as argument to addActionListener:
class YourClass implements ActionListener {
public void yourMethod() {
...
btnNewButton.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
lblNylabel.setText("New label text");
}
}
If I do the following,
final class FooButton extends JButton{
FooButton(){
super("Foo");
addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
// do stuff
}
});
}
}
am I letting the this reference implicitly escape?
Yes, the this reference escapes to the listener. Since this listener is not really an external class, I don't see any problem with it, though.
Here's where you could see that this escapes:
final class FooButton extends JButton{
Foo(){
super("Foo");
addActionListener(new ActionListener(){
private buttonText = FooButton.this.getText(); // empty string
#Override
public void actionPerformed(ActionEvent e){
// do stuff
}
});
this.setText("Hello");
}
}
Yes, because in the anonymous inner class you could access it like this:
final class FooButton extends JButton {
Foo() {
super("Foo");
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
FooButton button = FooButton.this;
// ... do something with the button
}
});
}
}
The code of the anonymous ActionListener could in principle be called and use the FooButton before the FooButton object is fully initialized.
Yes, the anonymous inner class of ActionListener has a reference to this.
Yes. this of the enclosing class is implicitly in an non-static anonymous class.