Java link event to event handler - java

I'm working on a GUI library for my game, and I'm trying to find a good way to link events from GUI elements (for example a click-event from a button) to a event handler.
Say I have a button called MyButton.
I would use the following code to set it up (incomplete, just for demonstration):
Button MyButton = new Button();
MyButton.SetParent(MyContainer);
MyButton.SetText("Text inside my button!");
MyButton.SetTextColor(Color.BLACK);
Now this code would be called in one of my gamestates, and what I would like to do is something like this:
MyButton.OnClick(MyButtonClickEvent);
public void MyButtonClickEvent(EventArgs event) {
}
The structure of my gamestates and containers and elements are:
GameEngine->GameState->Container->Elements
What would be the closest solution for this? Thanks in advance.

Java does not have methods as first-class functions, i.e., the language does not provide references to a method which you could pass around like you can in other languages. Your best bet for a construction like the one outlined in your question is to use reflection.
import java.lang.NoSuchMethodException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
public class MyButton {
private Object onClickObject;
private Method onClickMethod;
public void OnClick(Object object, String methodName) throws NoSuchMethodException {
OnClick(object, object.getClass().getMethod(methodName));
}
public void OnClick(Object object, Method method) {
this.onClickObject = object;
this.onClickMethod = method;
}
// MyButton calls this method every time the button is clicked, in
// order to inform the external event handler about it
protected void onClick() throws IllegalAccessException, InvocationTargetException {
onClickMethod.invoke(onClickObject);
}
}
But also note that because methods are no first-class citizens, the above is not the canonical way to implement event listeners in Java. Instead, the Java-way would be to define an interface with a callback method, maybe like this:
public interface ButtonListener {
public void OnClick();
}
(This is assuming you don't have to pass any parameters to the event handler. Usually, this cannot be assumed, thus in addition to a ButtonListener, you'd also have a ButtonEvent which encapsulates the parameters and which is passed to the method(s) defined in the interface.)
Then if you write a class that is interested in receiving events whenever a certain button is clicked, that class would have to implement ButtonListener. In turn, the MyButton class would have to provide a method to register listeners:
public MyButton {
protected List<ButtonListener> buttonListeners;
public void addButtonListener(ButtonListener listener) {
...
}
public void removeButtonListener(ButtonListener listener) {
...
}
protected void fireButtonEvent() {
...
}
}
I'm sure you've seen that pattern in the Java standard class library quite a bit, especially in java.awt and javax.swing -- see for instance java.awt.event.ActionListener, which is what AWT uses for button events.

Related

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.
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) {
}
}

ActionEvent confusion

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?

How to create change listener for variable?

Let's say I have some variable defined using the statementint someVariable;. While the code runs, the variable's value changes.
How can I track the changes in this variable? How could I implement some Listener that behaves like onSomeVariableChangedListener?
I also need to know when some other method in one page has been executed so I can set a Listener in another class.
Java gives you a simple Observer pattern implementation for this kind of thing, but you'll need to set your observed variable within a method that manages listener notifications. If you can't extend Observable, you can either use composition (i.e., have an Observable instance in your class to manage notifications), or you can take a look at java.util.Observable to get an idea of how to roll your own version.
Flux.java
import java.util.Observable;
public class Flux extends Observable {
private int someVariable = 0;
public void setSomeVariable(int someVariable) {
synchronized (this) {
this.someVariable = someVariable;
}
setChanged();
notifyObservers();
}
public synchronized int getSomeVariable() {
return someVariable;
}
}
Heraclitus.java
import java.util.Observable;
import java.util.Observer;
public class Heraclitus implements Observer {
public void observe(Observable o) {
o.addObserver(this);
}
#Override
public void update(Observable o, Object arg) {
int someVariable = ((Flux) o).getSomeVariable();
System.out.println("All is flux! Some variable is now " + someVariable);
}
}
This is one of the many reasons to hide variables behind setter/getter pairs. Then, in the setter you can notify your listener that this variable has been modified in the appropriate way. As the others have commented, there is no built in way to do exactly what you want, you need to implement it yourself.
Alternatively Benjamin brings up an interesting pattern, called the Decorator pattern, which might be useful to you if the code in question cannot be modified. You can look up more info at Wikipedia
The idea is to build a compatible wrapper around an object. Lets say your object in question is of type MyClass.
class MyClass{
public void doFunc(){...}
}
class MyLoggedClass extends MyClass{
MyClass myObject;
public void doFunc(){
//Log doFunc Call
myObject.doFunc();
}
}
instead of
MyClass object = new MyClass();
You would use
MyClass object = new MyLoggedClass(new MyClass());
Now your rest of the code would use object as per normal, except that each function call will be logged, or notified, etc.
As you will see in Wikipedia, this is typically done via an interface that the class in question inherits from, but this may not be possible in your case.
You could use View Model. First create a class that extends view model. I called mine NameViewModel.
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
public class NameViewModel extends ViewModel {
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName(){
if(currentName == null){
currentName = new MutableLiveData<>();
}
return currentrName;
}
}
then in activity that the variable value change first define an instance of your NameViewModel class :
private NameViewModel mNameViewModel;
then in onCreate use this code snippet
mNameViewModel = ViewModelProvider.of(this).get(NameViewModel.class)
mNameViewModel.getCurrentName().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String name) {
//do what you want when the varriable change.
}
});
if you want to change the value of name you could use this code snippet:
mNameViewModel.getCurrentName().postValue(String newName);
I use postValue() since I want to update variable from worker thread if you are on UI thread you should use setValue().
Now every time the variable are changed it update the UI.
I believe you will have to implement Observer Pattern.
There is no built-in way in Java to get a notification if the value of any arbitrary variable changes or if some method has been called.

Java callback methods

Can anybody help on how to implement callback methods using annotations in java ?
More detail -
Basically, I have a java method that returns nothing [void] but I wanted it to return the state of the object to the caller without changing the method signature using callback function. Hope that helps.
Thank you!
Very simple.
In some class or interface somewhere you have a method that should be called:
[access modifier] [return type] name([parameter list])...
for instance:
public void callback()
Then in some class you either override that method, or implement it, or something. Then in the code that does the callback you take an argument of the type of the class that has the callback method. For instance:
public interface Callback
{
public void callback();
}
public class Callbackee implements Callback {
public void callback()
{
System.out.println("Hey, you called.");`
}
static{
new Callbackee().doCallback();
}
}
public class CallBacker {
Callback call;
public void registerCallback(Callback call) {
this.call=call;
}
//then just do the callback whenever you want. You can also, of course, use collections to register more than one callback:
public void doCallback() {
call.callback();
}
}
If you want to see examples of callback methods in the Java API, look at MouseListener, MouseMotionListener, KeyListener and so forth. Usually you can register more than one callback of course.
Here is a nice tutorial about that:
http://slesinsky.org/brian/code/annotated_callback.html
Although I'm not sure if this is the thing you're thinking about.
You could wrap your Callback method in an http://download.oracle.com/javase/1.4.2/docs/api/java/awt/event/ActionListener.html class, then call ActionListener#actionPerformed(ActionEvent ev)

Java Event Binding

I'm new in windows application development using java. The question is this "How to i bind events to custom class methods?
As fas i have seen i can register listener classes to swing components to handle events. That is OK but i have to implement a class that implements e.g. the ActionListener interface to handle an event and then implement the actionPerformed method. That means ONE class FOR each event i have to handle?
Can't i have ONE class "listening" for events from all components and have each method in this class do the event handling?"
An example:
class MyEventListener { //pseudo code [no constructors, etc]
public void handleSubmitFormBtn(Event e) {
}
//other methods go here handling events from other swing components
}
Note: I am not sure about the method signature but i hope that you get the point.
Conclusion: ONE method to handle events fired from swing components..is it possible? Is the creation of ONE class for each the event the only way? Can't i route event handling to specific methods for a single class?
In swing what you usually do is use an anonymous class to handle your events, like so:
someControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// handle the event
}
});
Although you can basically have one class handling all your events, and register it to all handlers, anonymous classes, as mentioned above, are the correct swing idiom for handling events.
You can find much more info # http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html
You have a few choices, each with their particular benefits/drawbacks.
anonymous inner classes
component.addActionListener(
new ActionListener()
{
public void actionPerformed(final ActionEvent e)
{
outerClassesMethod();
}
});
inner class
class Foo
implements ActionListener
{
public void actionPerformed(final ActionEvent e)
{
outerClassMethod();
}
}
outer class
public class Foo
implements ActionListener
{
private final OuterClass target;
public Foo(final OuterClass t)
{
target = t;
}
public void actionPerformed(final ActionEvent e)
{
target.targetClassMethod();
}
}
class implements listener
public class OuterClass
implements ActionListener
{
public void actionPerformed(final ActionEvent e)
{
method();
}
// somewhere else in the code
{
component.addActionListener(this);
}
}
Each way has good and bad to it.
The anonymous inner class will not allow you to do what you are asking, it can only implement one listener.
The other three will all allow you to do what you want (just add , WindowListener to the implements list for exaple). You likely want the inner class or outer class implementing the listener way to do what you want. I suggest that because the listener is likely very highly coupled to your program, and you will need to do a large set of "if" statements to figure out which control was acted on to perform the actual action (you use evt.getSource() to figure out which control was being acted on and then comare it to your instance variables to see which it was).
However, unless you are in memory constrained device, such as an Android phone, you probably should not do one method for all listeners as it can easily lead to very bad code. If memory is an issue, then go for it, but if it isn't you are better of doing one of the following things:
one listener class per control
one listener class per event type for all controls
one listener class per control per event type
I prefer to code the following way, I find it to be the most flexible:
public class Outer
extends JFrame
{
private final JButton buttonA;
private final JButton buttonB;
{
buttonA = new JButton("A");
buttonB = new JButton("B");
}
// do not put these in the constructor unless the Outer class is final
public void init()
{
buttonA.addActionListener(new AListener());
buttonB.addActionListener(new BListener());
}
private void aMethod()
{
}
private void bMethod()
{
}
public void AListener
implements ActionListener
{
public void actionPerformed(final ActionEvent evt)
{
aMethod();
}
}
public void BListener
implements ActionListener
{
public void actionPerformed(final ActionEvent evt)
{
bMethod();
}
}
}
I prefer this way because it forces the methods out of the listeners, which means I only have one place to look for the code (not scattered throughout the inner classes). It also means that it is possible that aMethod() and bMethod() can be reused - if the code is in a listener that isn't practical (it is possible, but not worth the effort).
Doing it the above way is also consistent, and I prefer consistency over most things unless there is a good reason not do it. For instance on the Android I do not do that since class creation is expensive (I still have the listener call methods only, but the class itself implements the listeners and I do an if statement).
You can do this by creating a single action listener that then switches based on the input source, so something like:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonA) {
doSomethingForButtonA(e);
} else if (e.getSource() == buttonB) {
doSomethingForButtonB(e);
}
}
But this is not the recommended way to do it for various reasons. Why do you have an issue with creating a listener for every event to be received? It's the Java model for handling UI events, and if anyone else uses your code or you ever use someone else code it's going to be expected.
You can have one class which has listener methods of many events:
class EventHandler implements ActionListener, ..., MouseListener {
// implementation
}
A conceptual Solution would be to implement the OBSERVER PATTERN.
Melasse framework allows to glue UI component with model w/o creating class (even anonymous one), with syntax Binder.bind(/* source, target, options */).
For example not new class is needed to enable an action/button only when some text is present in a textfield: https://github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided-value . Same to display/hide informational or error label.
Most UI components are supported, all Java Beans (with property change support) are.

Categories