Dan Dan - 4 months ago 10
Java Question

How do you add new functions to pre-existing java components?

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.

Answer

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.