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) {
}
}
Related
OK, I am going to try to explain this as best as I can. I am fairly proficient at Java but am unable to find a logical solution to this after extensive searching. Lets say that I have a JPanel class inside package A that will contain a graph that will be drawn.
package A
public class DrawGraph extends JPanel
{
public DrawGraph()
{
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// other stuff
}
public void updateGraph()
{
repaint();
}
}
In a different class inside package B I have a JCheckBox that when selected should trigger a repaint of the graph in package A. This class does not initialize the DrawGraph class. That class is initialized elsewhere.
package B
public class CheckBoxClass extends JPanel
public CheckBoxClass
{
graphicsCheckBox.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent cb)
{
GUI_Data.graphics = true;
DrawGraph.updateGraph(); // Calls Update Graph function
}
});
}
Now how do I call the updateGraph function in my DrawGraph class without having to create a new instance of the DrawGraph class? I know that I cannot make the updateGraph method static since repaint() is not static. I feel like there has to be a way to do this without repainting via a timer or some other convoluted and inefficient method. Am I looking at this problem in the wrong way? Basically I need a way to trigger a repaint of the DrawGraph class from the JCheckBox class actionlistener. If this question isn't clear, please let me know so I can revise it. Thank you guys in advance, this is my first question but I have been using you guys for several years.
There seem to be a bit of confusion of concepts here, let me try to explain.
static vs. instance methods:
A class can have static and non static methods. non-static methods can be called only on an instance of the class. static can be called only on the class (although you can call them through a variable containing an instnace of the class).
method visibility: a method can be private, protected, package-protected or public. private methods can be called only from within the same class). protected can be called only from within the class or subclasses. package-protected (without any qualifier) can be called from classes within the same package. public can be called from anywhere.
In your case, the fact that the CheckBoxClass is not in the same package has nothing to do with the fact that you can't call DrawGraph.updateGraph(). updateGraph() is an instance method (non-static), hence you have to have an instance to call it. Now, if you know that there is going to be only one instance of DrawGraph in your program, then you can use the singleton pattern:
1) in the DrawGraph class have a static variable initialized to an instance of the class itself. Also have a static method that returns such instance:
public class DrawGraph {
private static DrawGraph singleton = new DrawGraph();
public static getInstance() {
return singleton;
}
}
Now you can do the following from CheckBoxClass:
#Override
public void actionPerformed(ActionEvent cb)
{
GUI_Data.graphics = true;
DrawGraph.getInstance().updateGraph(); // Calls Update Graph function
}
I'm refactoring some legacy system written in Java, and I came across a problem with an enum constructor.
I have an enum class like this (just an example):
public enum Signal{
ON(new InButton()),
OFF(new OutButton())
private final Button button;
Signal(Button button) {
this.button = button;
}
}
InButton and OutButton extends the Button interface.
The enum values are accessed for the first time using Signal.Values() method.
(Also, in one of the Button method, I have a code that uses the enum, such as activateButton(Signal.ON))
While refactoring the code, I wanted to create a new constructor for Button that express it dependency, such as Button(String input).
The problem is that I don't know how to pass the new parameters to the enum button field.
What is the right way to deal with this situation?
Is this enum should be used at all?
Clarification after Jean Logeart question: InButton and OutButton also have a constructor with a String arguments.
I'd rather avoid it to be initialize to null because than it could create other problems.
Basically this question is how to mimic a=f(x) using java syntax. Most of the time I can do:
y = new x(); a = new f(y);
a = new f(new x());
a = new f(null); a.getF().setX(new x());
In this case I can't do it.
I suggest not having the enums know about the buttons at all. Just have them enumerate the possible signals, and put the job of mapping signal->button somewhere else:
Function<Signal, Button> signalToButton = ...
That will also make it easier to inject different buttons for testing; for instance, you can inject a mocked Button that confirms that it was our wasn't pressed.
As far as using that mapping in your code: you can "install" a mapping to some static field, or, better yet, provide it as a constructor argument to any code that needs it. Dependency injection is very helpful for the latter option, but that may be a bigger change.
Two main options.
First one, InButton and OutButton also have a constructor with a String argument in which case you need to provide a String when instanciating:
public class InButton extends Button {
public InButton(String s) {
super(s);
}
}
// ...
public enum Signal{
ON(new InButton("in"))
// ...
}
Second option, InButton and OutButton are instanciated with a specific String in which case no refactoring is necessary in the enum:
public class InButton extends Button {
public InButton() {
super("in"); // default value
}
}
// ...
public enum Signal{
ON(new InButton()) // same as before
// ...
}
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?
I need to make objects for my buttons in my typing tutor.
I have made a class:
public class KeyLabel extends JLabel {
public KeyLabel(String name) {
setText(name);
}
this is my subclass
my superclass is the keyboard class
and I need to make objects for each button on my keyboard for my typing tutor, so the a is a label its the keyboard
but I don't know how to do this?
I don't know why are you extending JLabel if you are to create Buttons. Extending JLabel will create a JLabel which will be wasted as in your code. More relavent code would be like
public class KeyLabel {
public KeyLabel(String name) {
JButton buttonOK = new JButton("OK"); //creates OK button
}
}
Moreover, i think you should look here, for details.
In most cases, you'll want to use inheritance (i.e. subclass JButton). For instance,
public abstract JKeyboardButton extends JButton{
public JKeyboardButton(final String key){
super(key);
// include other stuff, if necessary
}
// include other methods common to all JKeyboardButton instances
}
And then for each concrete button, you'll want to subclass JKeyboardButton, like so
public final class JKeyboardAButton extends JKeyboardButton{
public JKeyboardAButton(){
super("a");
}
// override/implement other methods..
}
And then in order to obtain a keyboard key of, let's say a, all you have to do is create an instance of JKeyboardAButton, like so
final JKeyboardButton aButton = new JKeyboardAButton();
And then obviously you'll have to create a class for each key and throw all these instances into a Keyboard class. But I'll leave the "heavier" coding to you.
Also, please note that the final modifier is not required, but rather is a personal preference of mine (i.e. to prevent subclassing and to ensure that a variable (even local ones) are only assigned once).
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();