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.
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);
}
};
}
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");
}};
I am a beginner and not so familar with Java yet, so the solution to this might be simple.
I have one MainClass that includes the main method. This MainClass creates a JFrame which can have various JPanels inside. I have one class called CommandInput which creates a JPanel containing a JTextArea. Now I want that when the user closes the JFrame of the MainClass that it asks if he wants to save the changes. As the JPanels inside the JFrame vary I do not really want to include this in the MainClass. I know that it is possible for every "SubClass" like the CommandInput to add a windowListener to the JFrame of the MainClass but that does not really seems efficient to me:
public class CommandInput {
public CommandInput(JFrame mainFrame) {
mainFrame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override //Overwrites the normal behavior of this method
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
System.out.println("Closing Event triggered and detected by CommandInput object");
}
});
}
}
Should I maybe rather have one WindowAdapter in the MainClass and add this code to its windowClosing method? And if so how would I do that?
I now solved it in a way that each SubClass adds an anonymous inner class of an interface containing a method that returns if the JFrame can be closed to a list. Only if all of the anonymous inner classes in the list return true the JFrame closes:
public interface ClosingListener {
public boolean allowClosing();
}
public MainClass {
private ArrayList<ClosingListener> closingListeners = new ArrayList<ClosingListener>();
public MainClass() {
JFrame frame = new JFrame();
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
boolean canClose = true;
for (ClosingListener closingListener : closingListeners) {
if (!closingListener.allowClosing()) {
canClose = false;
break;
}
}
if (canClose) {
System.exit(0);
}
}
});
}
public void addClosingListener(ClosingListener closingListener) {
closingListeners.add(closingListener);
}
}
May be you need this
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
int choice = JOptionPane.showConfirmDialog(null, "Save changes?");
if(choice==0) System.exit(0);
}
});
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.