I'm making a game in Java, and I think I have a good idea of how to handle events. Does this sound right?
A Window class--the view. It's a representation of the World at the current moment.
There's also a Game class -- the controller. (The model's implementation is irrelevant for this question).
The Window class doesn't care about events. Therefore, the event listener simply dispatches them to the Game class (via something like game.notifyEvent(Event e);.
The Game class, upon receipt of this event, will start updating values and the like, and some variables (like the location of the player) will be changed. At this point, it uses its class variable Window w to notify it of the changes (via various methods such as w.movePlayer(Position p), etc.
SO, does this sound like something that would make sense to you?
Yes, what you're doing makes some sense. I find it much more intuitive to have the Window listen to the Game than the other way round. I've also found that Java is much more maintainable if you separate out the different areas of the GUI and pass the Game into each of them through a fine-grained interface. I normally get the GUI elements to listen to changes in the model, and request any interactions to be dealt with. This way round makes for easier unit testing, and you can replace the GUI with a fake for acceptance testing if you don't have a decent automation suite, or even just for logging.
Usually splitting up the GUI results in some panels purely listening, and some panels purely interacting. It makes for a really lovely separation of concerns. I represent the panels with their own classes extending JPanel, and let the Window pass the Game to them on construction.
So for instance, if I have two panels, one of which displays the results and one of which has an "Update" button, I can define two interfaces: INotifyListenersOfResults and IPerformUpdates. (Please note that I'm making role-based interfaces here using the IDoThisForYou pattern; you can call them whatever you like).
The Game controller then implements both these interfaces, and the two panels each take the respective interface. The Update interface will have a method called RequestUpdate and the Results interface will have AddResultsListener. Both these methods then appear on the Game class.
Regardless of whether you get the Game to listen to the Window or the Window to the Game, by separating things through interfaces this way you make it much easier to split the Game controller later on and delegate its responsibilities, once things start getting really complicated, which they always do!
I think you should implement the Observer design pattern (http://en.wikipedia.org/wiki/Observer_pattern) without using .NET's events. In my approach, you need to define a couple of interfaces and add a little bit of code. For each different kind of event, create a pair of symmetric interfaces
public interface IEventXDispatcher
{
void Register(IEventXHandler handler);
void Unregister(IEventXHandler handler) throws NotSupportedException;
}
public interface IEventXHandler
{
void Handle(Object sender, Object args);
}
X denotes the specific name of event (Click, KeyPress, EndApplication, WhateverYouWant).
Then make your observed class implement IEventDispatcher and your observer class(es) implement IEventHandler
public class Dispatcher implements IEventXDispatcher, IEventYDispatcher ...
{
private List<IEventXHandler> _XHandlers;
private List<IEventYHandler> _YHandlers;
void Register(IEventXHandler handler)
{
_XHandlers.Add(handler);
}
void Unregister(IEventHandler handler) throws NotSupportedException
{
//Simplified code
_XHandlers.Remove(handler);
}
private MyMethod()
{
[...]
for(IEventXHandler handler: _XHandlers)
handler.Handle(this, new AnyNeededClass())
[...]
}
//Same for event Y
All the code is hand-written. I have little experience with Java but I believe this pattern may help you!
Related
I seen many conflicting recommendations on the internet including here on how to handle input with awt and swing and several people have worked on my code and its a mess.
options
implement KeyListener or extend KeyAdapter
^to the application's main class, use an anonymous class, use a private class or use an external input managing class.
to send the event object to each object that needs to know input, to send an array of keys pressed, or to make every class a listener and add it to the main class.
So I could have
public class Board extends JPanel implements KeyListener{
public Board(){addKeyListener(this);}}
or
public Board(){addKeyListener( new KeyListener(){...});}
or
public class Board extends JPanel {
private class PrivateListener implements KeyListener{...}
public Board(){addKeyListener(new PrivateListener());
or
public class PublicListener implements KeyAdapter{...}
public class Board extends JPanel {
public Board(){addKeyListener(new PublicListener());
or
addKeyListener(this);
addKeyListener(obj1);
addKeyListener(obj2);
and implements KeyListener can be replaced with extends KeyAdapter but I won't do that because java only allows for one parent class.
then there is which I don't know how this got into my code
private boolean [] keys = new boolean[256];
public void keyPressed(KeyEvent e) {keys[e.getKeyCode()] = true;}
public void keyReleased(KeyEvent e) {keys[e.getKeyCode()] = false;}
public boolean isKeyDown(int k) {return keys[k];}
or
public void keyPressed(KeyEvent e) {
obj1.keyPressed(e);
obj2.keyPressed(e);
}
Truly, what is the best implementation of awt keyboard input?
This is a solid "it depends" situation, and this answer is open to plenty of academic discussion.
My Oppinion:
This is definately just an oppinion, but I would recomend talking to your coders and agreeing on two things. Make your decision based on the answers, and put it in the README at the base of your code:
Anonymous classes, or not?
Mega classes, or not?
Assuming prefering small, named classes I would go for the following.
public class PublicListener implements KeyAdapter{...}
public class Board extends JPanel {
public Board(){addKeyListener(new PublicListener());
Using KeyAdapter you will only have to override the functions you care about, and other programmers can see quite easily that this is where the input is handled as it is in its own class.
TLDR
Firstly, wanting to work with low level classes is a valid desire. In production code I would not recomend it, but AWT is still the basis of Swing, and wanting to learn is not to be discouraged! If nobody learns the low level stuff, then one day the open source community will have a big problem being built on top of code, which nobody has learned.
While the comments on Swing and Key Bindings are valid, in the documentation about Swing Key Bindings, there is the quote:
An alternative to key bindings is using key listeners. Key listeners have their place as a low-level interface to keyboard input, but for responding to individual keys key bindings are more appropriate and tend to result in more easily maintained code.
So if you are in it to learn some low level stuff, go for it, but take note of the maintainability warnings!
The rest comes down to two main point. Coding Style and Application Architechture.
Coding Style:
Consistency across a code base is often more important than having the perfect implementation, so if you have a codebase with an existing style, then stick to that style. For example, if your codebase already uses lots of Anonymous Classes in other places for other things, then adding a new KeyListener(){...} is fine. That said, in my personal projects I avoid anonymous classes, because personal preference...
The decision for (what I call) Mega and Mini classes is also important in coding style. The very clear recomendation is to prefer small (mini) classes, with specific roles. This would support implementing a dedicated class which extends KeyAdapter. Mini classes rarely struggle from multiple inheritance problems, allowing you to rely on default implementations (like KeyAdapter), further reducing your code complexity. Future coders can then very easily see what that class is for. Mega classes centralise all of the code into one java file, but then you will be implementing lots of interfaces, and also having to provide default implementations for everything. Compairing KeyListener to KeyAdapter this means implementing three functions instead of overriding one.
Mega classes have their place because multiple inheritance. A "Player" can be a Human, "PositionProvider", a "Drawable" etc. But in all seriousness, this is just not recommended.
Architechture:
Games programming was mentioned, so this is also an important consideration. The architechture of a game can be very different to a dektop GUI application. You need to pick an architechture, and make code which sticks to it. E.g. are you planning to let several components listen to the AWT events and act independantly (entities), or do you plan to have a seperate "InputManager" class, which abstracts input from e.g. keyboard and joypad?
How can I call a method from a class that is not an object within another class, and has nothing in common with this other class?
In my case:
class GridUI {
com.google.gwt.user.cellview.client.DataGrid grid;
public void refresh() {
dataGrid.redraw();
}
}
class SomeBackendService() {
public foo() {
//have to trigger refresh of a specific grid
}
}
One possibility might be to make the refresh() and grid static. But that's bad design, and I cannot use this approach as I want to use several implementations of GridUI.
So, how can I refresh a certain gridclass in my app from any service that does not contain this grid as an object??
Just create and fire an Event for it in your service and make your grid register for that Event. It's probably best to use an EventBus.
Using a static Map<String, Grid> as was suggested in the accepted answer will work but it's not proper. You risk making mistakes and it's not as easy to manage when the number of grids increases.
The EventBus approach is more work upfront but in the end it's a better approach. You'll be able to reuse the EventBus throughout your application. It really helps keep your coupling down. You'll also easily be able to get different objects act on the same Event with little effort.
Alternatively create a components registry (basically a Map<String,Grid>), then fetch the grid from SomeBackendService using its id as key in the registry. (I guess you know which grid you want to refresh, right?)
Be careful with registries though:
make sure they are thread safe if need be (probably true in an UI app)
they tend to fill up and leak memory if not properly handled
Sorry for not answering that long time, i was in vacation.
Interfaces are some kind of classes.
But they do not implement any method, they have empty method bodies.
Each class, which implements an interface usually MUST implement its methods.
In C# You would Do :
enter code here
interface IMyInterface
{
void PleaseImplementMe();
}
class clMyInterface :IMyInterface
{
void IMyInterface.PleaseImplementMe()
{
MessageBox.Show("One implementation");
}
}
end
Please let me know, whether this is what can help You or not.
I'm building an Android app and a Blackberry app (same app different platforms). There is an abstract class that I am building that will handle events. For instance, I touch the "save" button on Android it posts a notif/event. The abstract class receives that event. I press the "save" button on Blackberry, it does the same thing.
What is the best way to accomplish this? I've looked at EventObject, as well as MBeans and its notification classes but they appear overly complicated. In objective-c I simply register a class instance for notifications with the objective-c notificationcenter, and then in the class that triggers the notif, at the time of trigger we do something along the lines of "postNotification". Is there anything that easy in Java? Also I need to send Objects with those notifications.
Oh at I suppose we actually can't use any MBeans classes. Not part of Blackberry Java version.
Thanks!
With BlackBerry, if you're planning on these events to be generated from UI elements (ButtonField, ListField, etc) they all come with Field.setChangeListener(FieldChangeListener) so you just have to attach a listener to that. If you want this to be something that responds to things like IO or processing, you could use the Event and EventListener classes to accomplish this. Personally I think they're a little more than what I need for simple notifications, so I generally make my own simple interfaces.
Say you have a class that extends Thread that connects to a web service to download an XML file that lists states and their capitals. and processes it. You could create an interface EventGenerator with abstract methods public void addEventHandler(EventHandler) and protected void notifyHandlers(Object obj). Inside of this you have a Vector that stores EventHandlers that your notifyHandlers() can loop through and send a call to handler.handleEvent(Object). When you are finished with processing the data, you wrap it up in an Oject (maybe Hashtable, or a custom States bean), we'll call it states, and internally call notifyHandlers(states). Now as you go through each EventHandler, you call handler.handleEvent(states). You may consider putting a try/catch around each call to it so one EventHandler doesn't prevent all of them from running.
So onto the EventHandlers. This is another interface that has the abstract method public void handleEvent(Object obj). Say you have a Screen that, after the states are retrieved, will display them in a list. This Screen will implement EventHandler and then register itself with the EventGenerator using generator.addEventHandler(this). Whenever the processing is done, this method will get called and you can do whatever you want with the Object that is returned.
An addition you can implement is changing public void handleEvent(Object obj) to public boolean handleEvent(Object obj) and, similarly to navigation methods in BB, return true if the event was handled and nothing else should try processing it.
I wrote a Listener. Now I want to notify it, when a change occurs. Nothing special.
Now I'm asking myself:
Is there I standard class for Events that I can use, or do I have to write a new one by myself?
I know there ara java.awt.Event and AWTEvent. But I am not working directly at GUI level here. Furthermore we are using Swing at GUI level. So I'm not shure if it is a good idea to mix Swing and AWT.
Thx
Its ancient and simple, but you could use Observer/Obserable in java.util:
java.util
public class Observable extends Object
This class represents an observable
object, or "data" in the model-view
paradigm. It can be subclassed to
represent an object that the
application wants to have observed.
An observable object can have one or
more observers. An observer may be any
object that implements interface
Observer. After an observable instance
changes, an application calling the
Observable's notifyObservers method
causes all of its observers to be
notified of the change by a call to
their update method.
For more info, try http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto.html.
There's nothing special about events in Java. If your events are not GUI events, then it would be less confusing for you to use your own class and not mix them with java.awt.Events.
If you are using swing, you can take a look at EventBus:
The Event Bus is a single-process publish/subscribe event routing library, with Swing extensions. The EventBus is fully-functional, with very good API documentation and test coverage (80+%). It has been deployed in many production environments, including financial, engineering and scientific applications.
I've always used EventObject as the base class for my custom events. Here's what the JavaDoc says:
The root class from which all event state objects shall be derived.
All Events are constructed with a
reference to the object, the "source",
that is logically deemed to be the
object upon which the Event in
question initially occurred upon.
Kind of a standard solution in Swing apps is to maintain a list of event listeners in the class the event originates from. When the event occurs you iterate over the list and notify each listener of the event. So it can be something like this (I omitted the access modifiers and some of the type declarations for brevity):
class SomeClassInWhichTheEventOccurs {
List<MyListener> listeners;
void addListener(listener) { listeners.add(listener); }
void removeListener(listener) { listeners.remove(listener); }
void fireEvent(someEventParameters) {
foreach (listener in listeners) listener.eventOccured();
}
void someMethodInWhichTheEventOccurs() {
...
fireEvent(someEventParameters);
}
}
The event parameters can be just anything: you can create your own event class, reuse java.awt.Event, or pass some parameters of arbitrary types.
Swing is based upon AWT, so you have to mix it. The problem comes with mixing AWT heavyweight components with Swing lightweight components. Don't use AWT heavyweight components.
Just to be notified that something has changed javax.swing.event.ChangeListener is fine. In fact, so long as you are not using a library that assumes the beans model, you can ignore event classes and use a observer without an event object.
My current application has a JFrame with about 15 actions stored as fields within the JFrame. Each of the actions is an anonymous class and some of them are pretty long.
Is it common to break actions into their own classes possibly within a sub-package called actions?
If not, how's this complexity usually tamed?
Thanks
If it is possible that your actions could be reusable (e.g., from keyboard shortcuts, other menus, other dialogs, etc.) and especially if they can work directly on the underlying model (rather than on the UI), then it is generally better not to have them as anonymous classes.
Rather, create a separate package, and create classes for each.
Often, it also makes sense to not instantiate these directly but rather have some sort of a manager that defines constants and initializes and returns sets of actions, so that you could, for example, offer different action sets at different versions or set certain actions only for internal releases.
Finally, check whether your actions can be refactored into a class hierarchy. They often can, which saves code replication, and also helps you add robustness (e.g., check for certain conditions before letting the action execute).
That's typically how I do it. Each action gets it's own class which has a reference to the "app" object so it can get to resources it needs. I usually have an action manager that holds all the actions so there's one place to access them as well as one place to update their enablement and stuff.
Eventually this also becomes unmanageable at which point you should start thinking about using an app framework like Eclipse RCP, the NetBeans framework, JIDE, etc. This is especially true if you want to support user-defined keymaps and stuff like that.
What I do is create a package (package tree actually) for action classes, then instantiate each class according to context. Almost all of my action classes are abstract with abstract methods to get the context (ala Spring).
public abstract class CalcAndShowAction extends AbstractAction {
//initialization code - setup icons, label, key shortcuts but not context.
public void actionPerformed(ActionEvent e) {
//abstract method since it needs ui context
String data = getDataToCalc();
//the actual action - implemented in this class,
// along with any user interaction inherent to this action
String result = calc(data);
//abstract method since it needs ui context
putResultInUI(result);
}
//abstract methods, static helpers, etc...
}
//actual usage
//...
button.setAction(new CalcAndShowAction() {
String getDataToCalc() {
return textField.getText();
}
void putResultInUI(String result) {
textField.setText(result);
}
});
//...
(sorry for any mistakes, I've written it by hand in this text box, not in an IDE).