Im new to Java and today i have a problem with my code when I trying to do ActionListener
My java class look like here:
public class exam{
private void createForm(){
...
JButton jbtn = new JButton("OK");
jbtn.addActionListener((ActionListener) this);
...
}
public static void main(String[] args){
exam ex = new exam();
ex.createForm();
}
public void ActionPerformed(ActionEvent ae){
//IDE show that no variable name "jbtn"
if (ae.getSource() == jbtn){
...
}
}
}
Your jbtn variable is declared within the createForm method. Java uses what are called "scoping rules" to make sure you don't accidentally use variables you don't mean to. By declaring jbtn in createForm, you are telling the Java compiler that you only want to use it in that method, and nowhere else. This is called a "local" variable (as in, it is local to the method).
You probably want to use a "member variable" (it is a member of the class). This is declared inside the class, but outside of any method. In your case, this looks like this:
public class exam{
JButton jbtn;
private void createForm(){
...
jbtn = new JButton("OK");
jbtn.addActionListener((ActionListener) this);
...
}
The declaration of the variable is now at the class level, and in createForm it is being referenced in the same way as in ActionPerformed.
This is a fairly basic concept in Java, so you might want to take a look at some Java tutorials that go over this ground. The official tutorial is a good place to start.
Related
I am beginning to learn Java and one thing is confusing me.
I have created a class PMO where I have created a TextField and put some text in it.
I have created another class PublicMethodObject where I have created the JFrame.
Now, I want to add the text set in TextField by using JFrame that I created in PublicMethodObject class.
How can this be possible?
class PMO{
public void J2(JTextField f1){
JTextField f= new JTextField();
f.setVisible(true);
String s="Hellow World";
f.setText(s);
return f;
}
}
public class PassMethodObject {
public PassMethodObject() {
JFrame a=new JFrame();
a.setVisible(true);
}
public static void main(String[] args) {
}
}
Your question is pretty confusing.
Maybe you meant using one class's method in another class because that is what it seems you are trying to do.
To do that you simply have to create the object of the first class inside second class and then use it for accessing the member variable and field(methods) of the first class. Unless it is static in that case you can call it directly using class's name.
example:-
access modifier Class A {
access modifier return type method(){};
}
access modifier Class B{
A ob = new A();
ob.method();
}
And of course, you have to take account of the access modifiers (public,protected,private,default) as well.
To explain what I mean by this question I will use code examples below. Imagine you have this function.
private void fadeButton(JButton b, int timeToFade) {
//Fade code goes here
}
How would you implement this as a function which could be run like
JButton b = new JButton("Press Me");
b.fadeButton(20000);
Where fadeButton now looks like
private void fadeButton(int timeToFade) {
//Fade code goes here
}
Because the function is declared on the button itself.
Typically you create a derived class:
public JFadableButton extends JButton
This will contain the method private void fadeButton(int timeToFade).
Short answer is: you don't.
Longer answer:
You can't do that in Java directly (adding methods to a class outside of the source code of that class). That might be different in other languages, like Kotlin offers "something" like that.
In java, you have to make detours, for example by turning to the decorator pattern.
And just for the record: I didn't mention the simple "you can extend that class" because I read your question as "how do I add methods to JButton directly". But of course, creating your own class that extends JButton allows you to add methods; but of course, they only exist on objects of your derived class.
You could extend JButton with a new class, thus inheriting JButton's methods and adding the ability to add your own code:
public class FadingButton extends JButton {
//Constructors go here
private void fadeButton(int timeToFade) {
//Fade code goes here
}
}
You could also decorate the JButton with another class:
public class JButtonDecorator {
private JButton btn;
//Constructor here
private void fadeButton(int timeToFade) {
//Fade code goes here, hiding the held button
}
//getter and setter method for button
}
Or, if you want lots of different ways to affect your UI, you can make a utility class, similar to above:
//You could use a factory pattern to make this a singleton instead of having static methods
public abstract class UIUtils {
private UIUtils{} //Don't instantiate this class
public static void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other static utility methods
}
Edit: Making use of these patterns. The extended class is self-explanatory and an example of simple inheritance, so it's just a matter of JButton btn = new FadingButton(); for example. Here are the others:
To use the decorator, instantiate it at the same scope as the button you're using now. For example:
JButton myButton = new JButton();
//Customize button and add to UI
JButtonDecorator jbDec = new JButtonDecorator(myButton);
jbDec.fadeButton(20000);
Although the button is a field of the decorator, it will otherwise behave normally in your UI. The decorator just wraps the class with useful methods such as the fadeButton method.
To use the utility class, there are two ways. One is two make an abstract class with static methods (as above), some consider it bad form but it's good for simple programs:
UIUtils.fadeComponent(myButton); //It's just that simple!
//The UIUtils class itself is never instantiated.
//All the methods are static, so no instances are needed.
Or if you want a more advanced method, make your utility class a singleton. This changes the utility class to this:
public class UIUtils {
UIUtils singleton;
private UIUtils{} //Don't instantiate this class publicly
public static UIUtils getInstance() {
if(singleton==null) //This is the first time the method is called
singleton = new UIUtils();
return singleton; //Return the one instance of UIUtils
}
public void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other utility methods
}
Then you would declare your UIUtils object at class level to use across your UI:
UIUtils uiUtil = UIUtils.getInstance();
And somewhere in your code:
uiUtil.fadeComponent(myButton);
This pattern is more efficient with memory and is more object-oriented, but I don't personally find it very suitable for utility classes.
You can create a new class which extends JButton, and then add any method that could help you achieve what you want. But that's an exemple, there is many ways to achieve this.
Ps, don't set this method as private if you want to use it somewhere else than inside your class.
This is the simplest way I think think of. You have already got it. But just use this method:
private void fadeButton(int timeToFade) {
//Fade code goes here
}
This is assuming you already have the code for the fade, do you? I think this one is the one you should use. You don't need the button to be a parameter. When you want to call the method to fade the button, just put it in the ActionListener. So after you have the ActionListener for the button, do the following: btnName.fadeButton(timeToFade);
Here is how to code the ActionListener:
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
}
I'm very new to Java and I'm confused about the ActionEvent class.
I was under the impression that to use a class you had to create a new object for example:
SomeClass aClass = new SomeClass();
But in this piece of code:
private class theHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
Event.getSource()
// etc...
}
}
How come you don't need to:
ActionEvent event = new ActionEvent();
Event become an instance of the ActionEvent class without having explicitly tell it.
I'm sorry of this is a dumb question, I'm teaching my self Java, and this is thoroughly confusing to me.
ActionEvent is created somewhere, but it's just not being created explicitly by you. Rather, it's being created in the JButton's code (actually the code is in the AbstractButton class, a parent class for JButton) for notifying all ActionListeners that listener are attached to it. You can view the source file to see the details if you desire.
When you use implements in Java, what you are doing is using an interface. Interfaces require certain methods to be implemented in your code and offer a way to ensure new classes that implement a certain interface have methods that can be called.
Thus, in your example:
private class theHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
event.getSource()
// etc...
}
}
The ActionListener interface is being implemented by theHandler and therefore the method, actionPerformed(ActionEvent event) is required to be implemented by your class. There is no explicit ActionEvent event = new ActionEvent(); being created here because the ActionEvent is actually being passed through as a parameter to actionPerformed and is otherwise being created somewhere else.
Specifically for your example, you can also do the following instead of using the implements keyword on your class:
public class theHandler {
public theHandler() {
JButton button = new JButton();
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// do some stuff here
}
});
}
}
It's really quite simple, there is a thing called static methods. These are methods you can use from a class without making objects of them.
Like the Math class and all it's functions fx. a static method could look like this:
public class HiClass {
public static String sayHi() {
return "Hi!";
}
}
You would then use it in some context like this:
System.out.println( HiClass.sayHi() );
This would print out the string the method returns in your console.
You might ask "why wouldnt I just make all my methods in my classes static then?" there are many reasons, main one I can think of is that when you program you always try to restrcit responsibilities to classes that makes sense, so that the code is more manageable and easier to alter as the program grows.
This is not specific to the context your mentioning though, but it seemed to me your real question is how you can use methods without creating an object?
Hope it answers your question?
This question already has answers here:
What causes error "No enclosing instance of type Foo is accessible" and how do I fix it?
(11 answers)
Closed 6 years ago.
I get the error No enclosing instance of type mainframeclass is accessible when I try to compile/launch my program in Eclipse. Here is the code:
public class mainframeclass {
public static Object mainframemenuitem1;
public static void main(String[] args) {
JFrame mainframe = new JFrame(variables.mainframename);
mainframe.setLayout(new GridLayout());
mainframe.setSize(variables.mainframewith, variables.mainframeheight);
mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainframe.setVisible(variables.mainframevisible);
mainframe.setResizable(variables.mainframeresizable);
JMenuBar mainframemenubar = new JMenuBar();
JMenu mainframemenu = new JMenu("File");
JMenuItem mainframemenuitem1 = new JMenuItem("Exit");
mainframe.setJMenuBar(mainframemenubar);
mainframemenubar.add(mainframemenu);
mainframemenu.add(mainframemenuitem1);
actionlistener listen = new actionlistener();
mainframemenuitem1.addActionListener(listen);
runningclass.running();
}
public class actionlistener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == mainframemenuitem1)
System.out.println("Test");
}
}
}
It seems that I have done something wrong with the:
actionlistener listen = new actionlistener();
but I don't know what. I am new to Java and would appreciate any insight into this problem. Thanks.
Your actionlistener class (which should be renamed to follow Java naming conventions and with a more meaningful name) is an inner class (as opposed to a static nested class), which means it's only valid with an enclosing instance of mainframeclass to refer to... which it doesn't actually need, given that it refers to mainframemenuitem1 which is static anyway.
So you can just change it to:
public static class actionlistener implements ActionListener
and it should work. Well, it will compile, anyway. It won't actually do what you want because you've got two mainframemenuitem1 variables - the static one, and then a local one within your main method, so the static one never gets assigned a non-null value.
I would either pass mainframemenuitem1 into the constructor of actionlistener and still make it a static nested class, or just make mainframemenuitem1 final within the main method and create an anonymous inner class for the action listener.
Having said that:
i am kinda new to java
In that case, I would actually stop with GUIs entirely for the moment. It's much simpler to learn about a new language without the complications introduced by GUIs. Writing console applications allows you to concentrate on learning just one thing at a time.
I am writing a setonclick listner, and I want to be able to refer to that button so that I can change its properties. I.e. make it disabled?
I get thismessage:
Cannot refer to a non-final variable confirmButton inside an inner class defined in a different method
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
confirmButton.setEnabled(false);
}
});
This because you are probably trying to access that button from an anonymous class that you use in this way:
button.addActionListener(
new MyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//do your things on button }
}
}
);
This doesn't work because in Java anonymous classes cannot see variables declared in methods in which they are declared too since their scope are separated. The only way to let your class see it is forcing the final constraint which assures the compiler that the variable won't change after being initialized, allowing it to extend its scope to the anonymous classes.
To quickly fix this you can access the button from the ActionEvent inside the actionPerformed:
((JButton)e.getSource()).setEnabled(false)
Otherwise you have to concretely declare your ActionListener somewhere or declare the buttons outside the method with static or final attribute.. especially if you plan to modify some elements by an action that is fired by another element.
I would recommend against the getSource; the documentation doesn't promise that it will be your button. You can either make your button final in the scope, or use a more sophisticated class
public class ComponentRelevantOnClickListener implements View.OnClickListener {
private JComponent component;
public ComponentRelevantOnClickListener(JComponent component) {
this.component = component;
}
}
// then, in your code...
confirmButton.setOnClickListener(new ComponentRelevantOnClickListener(confirmButton) {
public void onClick(View view) {
component.setEnabled(false);
}
});
If you move toward a design of action and listener classes instead of anonymous subclasses, you get more chance for re-use (you can already see that ComponentRelevantOnClickListener could be replaced with a "DisableOnClickListneer" that you can use anywhere for this purpose), and your code will be overall better designed.
vars that are referenced within anonymous classes need to be defined as final in Java. Jon Skeet has a great example of this nestled within this article.
Anonymous inner classes can only access variables from the outer scope if they are final. Assuming you only assign to the confirmButton once, I suggest simply tagging it as final.
final JButton confirmButton = new JButton();