java - How to access AbstractButton's method from anonymous inner class? -
here class:
public class buttonpanel extends jpanel { public buttonpanel () { makebutton ("button1"); makebutton ("button2"); makebutton ("button3"); } void makebutton (string name) { jbutton button =new jbutton(name); add(button); button.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { settext("i clicked"); } }); } }
when button clicked, text should change "i clicked". however, don't know how access settext
method. tried button.settext("i clicked")
not possible.
by making reference of jbutton
final, :
void makebutton(string name) { final jbutton button =new jbutton(name); add(button); button.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { button.settext("i clicked"); } }); }
here 1 related example :
add action button created button
edit 1:
here 1 updated version of code, works mentioned before :
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class buttonexample1 extends jpanel { private jbutton makebutton (string name) { final jbutton button =new jbutton(name); add(button); button.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { button.settext("i clicked"); } }); return button; } private void displaygui() { jframe frame = new jframe("button example"); frame.setdefaultcloseoperation(jframe.dispose_on_close); jpanel contentpane = new jpanel(); contentpane.add(makebutton("one")); contentpane.add(makebutton("two")); contentpane.add(makebutton("three")); frame.setcontentpane(contentpane); frame.pack(); frame.setlocationbyplatform(true); frame.setvisible(true); } public static void main(string[] args) { runnable runnable = new runnable() { @override public void run() { new buttonexample1().displaygui(); } }; eventqueue.invokelater(runnable); } }
edit 2 :
here answer tries explain reason, why need declare final
to answer question, need understand basics, how jvm use work. when classes compiled contain inner classes, byte code gets generated not implement inner classes class within class.
why error : local variable accessed inner class, needs declare final
import java.awt.event.mouseadapter; import java.awt.event.mouseevent; import javax.swing.jmenu; import javax.swing.jpanel; public class foo extends jpanel { public foo() { final jmenu edit = new jmenu(); edit.getitem(0).addmouselistener(new mouseadapter(){ @override public void mouseclicked(mouseevent e) { if (e.getclickcount() == 1) { edit.getitem(0).setenabled(true); } } }); } }
when compile program, 2 files created, foo.class , foo$1.class. problem comes, since second
class i.e. foo$1.class
doesn't know variable
edit present inside first
class i.e. foo.class
.
so how solve problem ? jvm
does, that, it makes requirement developer make variable of outer class declared final.
now being done, jvm quietly places hidden variable name val$edit inside 2nd compiled class file, here output got javap
ouput foo.class
c:\mine\java\j2se\folder>javap foo.class compiled "foo.java" public class foo extends javax.swing.jpanel { public foo(); }
now since, edit local constructor, hence output above.
c:\mine\java\j2se\folder>javap foo$1.class compiled "foo.java" class foo$1 extends java.awt.event.mouseadapter { final javax.swing.jmenu val$edit; final foo this$0; foo$1(foo, javax.swing.jmenu); public void mouseclicked(java.awt.event.mouseevent); }
the variable
val$edit assigned same value has been assigned edit since compiler knows value cannot changed has been declared final , hence works time.
now if change edit variable
being local
being instance
. object of class knows variable edit, if gets changed. changing above program likewise :
import java.awt.event.mouseadapter; import java.awt.event.mouseevent; import javax.swing.jmenu; import javax.swing.jpanel; public class foo extends jpanel { jmenu edit = new jmenu(); public foo() { edit.getitem(0).addmouselistener(new mouseadapter(){ @override public void mouseclicked(mouseevent e) { if (e.getclickcount() == 1) { edit.getitem(0).setenabled(true); } } }); } }
here in case, not suppose declare , define being final
, because in case since variable
being local whole class, variable
send inner class along object reference
i.e. this
c:\mine\java\j2se\folder>javap foo.class compiled "foo.java" public class foo extends javax.swing.jpanel { javax.swing.jmenu edit; public foo(); }
here how variable
send in case i.e. this$0 :
c:\mine\java\j2se\folder>javap foo$1.class compiled "foo.java" class foo$1 extends java.awt.event.mouseadapter { final foo this$0; foo$1(foo); public void mouseclicked(java.awt.event.mouseevent); }
seems interpretation, how situation works, according me. found wonderful explanation on internet regarding mystery of accessibility in local inner classes, might understand situation in better way :-)
Comments
Post a Comment