I have dialog for storing user preferences of the application which is developed using Java Swing. There are 20+ preferences and I would like to notify other modules when the particular preference changes. I know that I can hold a list of listeners and notify them whenever the preferences change. However, I would like to know about two issues:
How can I bind my Swing components to a bean object,
How can I fire an event when the preferences change,
Dependending your experience, how would you resolve that architecture? What are the best practices to follow?
Thanks
I developed a Swing application where the user could modify some parameters to change functionality or the graphic of the application.
I approached it this way:
A general Setting abstract class represent a single value that the user can change.
A subclass is created for different types of value, in my case: boolean, integer, floating points, colors, etc.
I use a Map to keep track of the created Setting and a Preferences object to store the values.
For the actual settings, I create a static attribute somewhere (in my case, dedicated classes for different logical groups of settings) and use that attribute to read and change the values fo the settings.
PRO: The Settings keeps track of all the settings instantiated, so I don't need to code the frame for changing them twice, I just did it once in an indipendent way from the number of the settings
CONS: It clearly requires changing the code to add a new setting. While in my case it was not an issue because a new setting was needed only because of other changes in the code, in your case it might be.
Related
People here keep suggesting to me to use Key Binding instead of KeyListener in Java 2D games.
What are the advantages and disadvantages of each one? Is Key Bindings really better for 2D games?
KeyListener is a much lower level API which requires the component that it is registered to be focused AND have keyboard focus. This can cause issues when you have other components within your game that may grab keyboard focus, for example.
KeyListener is generally more difficult to maintain and extend or change, as typically, all the key events are channelled through a single listener, so ALL the game controls originate from this single position.
(Now imagine you want to add other controls, such as buttons or even joystick or controllers to mix - you suddenly have any number of input hubs you need to consider, keep up to date and in sync :P)
The Key Bindings API has been designed to provide re-usable Actions which can be used in a variety of different parts of the Swing API, while this makes desktop application development easier, it can also make it easier when developing games...
Apart from the fact that you now gain control over the focus level that the events are generated, you also gain the flexibility to defining configurable key's which can be mapped to different actions
For example...
You define an Up Action, which moves you character up. This is divorced from any event. That means, the Action does not care how it is triggered, only what it should do when it is triggered.
You are now free to define the keystroke which would trigger this action. The great part about this, is suddenly have the ability to provide customisation to the user, so they can actually define the key stroke they want for the action - for example, without having to design some kind of key mapping system of your own.
It also means that you can use the same Action (and even the same instance) in a variety of different ways. For example, you can bind the Action to a key stroke and add it to button and if you're brave enough to try, even bind it another input device (like a joystick or controller)...but you'd need to build the API yourself to achieve it, but it means you suddenly have a single API concept for all your user input, for example...
Key bindings were introduced later. They map actions to specific keys whereas a listener simply listens for which keys are pressed. To be honest, it doesn't really matter which one you use, but it's always preferable to use key bindings.
There are many libraries also available which have their advantages/disadvantages. Key bindings should be fine though for a 2D game. However, please note that using the Java API is not recommended for game development. If you ever want to build 3D, or content rich 2D games, it's much better to use OpenGL. Try LWJGL or JOGL (LWJGL is preferred generally) or you can use a game engine such as Slick2D or LibGDX.
After a few time enjoying the help of this site, the time to integrate myself here has come!
Well, I'm starting a personal project using java (under Windows 7), and I'm getting started with SWT. After a search of hours, I'm not satisfied with the short information I reached.
The project is an application where I will have a main window, from where the user can access to different modules (Customers Management, products management...).
What I want is to set properly:
A) I18n languagues
B) User preferences
"Properly" means a good,proper and easy access from all the components of the program to that data to use it, having in mind to do it through the most "standardized" way too.
I already created a package called "LanguagueResources", where I have the MessageBundle_xx_XX.properties, and I defined the following attributes on my MainMenu Class
protected String languague="en";
protected String country="UK";
protected Locale currentLocale=new Locale(languague, country);
protected ResourceBundle
messages=ResourceBundle.getBundle("MessageBundle",currentLocale);
With this, my main menu works fine with the different languagues. But what happens when I open a new window? maybe I can declare it this again (too much repeated code), or maybe I can pass some data when I call the new window instance (this doesn't look stylish). Same with other possible preferences settings.
This also makes me wonder how I must construct the program structre.I mean, is correct to start with a SWT Application window (Main Menu), and from there, call other SWT Application windows which will be the different modules (Customers, products)? Maybe must I establish an independent Main class where I will call MainMenu class, and where I will define the languague resources and preferences resources?
Also, I would like to know if the user preferences must be saved like the languages (.properties file)
I think I can do it trough many ways, but I would like to know which is the recommended,standarized and easiest way to do it.
I hope I explained well.Thanks in advance!
The GWT JavaDocs for the PlaceHistoryHandler#DefaultHistorian are vague and cyclic:
Default implementation of PlaceHistoryHandler.DefaultHistorian.
This doesn't really tell us what it is, or what it does!
Then we have the PlaceHistoryMapper and the ActivityMapper objects. My understanding is that the PlaceHistoryMapper's job is to map URL tokens to Place, and that ActivityMapper maps those Places to Actvitity implementations.
So I ask: if these two Mappers take care of binding a URL token to a specific Activity, then what role does the DefaultHistorian play in all of this?
Javadoc is easy to correct at read time: DefaultHistorian is the default implementation of Historian.
To understand how they all play together, you first have to understand that places can work without history, and also without activities.
So, in the central place are places: PlaceController keeps a current Place (getWhere), which can be modified by goTo and broadcasts change events to an EventBus. Listeners can ask the user to confirm (PlaceChangeRequestEvent's setMessage) through Delegate (whose default implementation uses Window.confirm).
Built on top of PlaceRequestChangeEvent and PlaceChangeEvent are activities. You can have several ActivityManagers, each one with its ActivityMapper and a display region, displaying a different activity each for the same given/current place.
And on the other side, based on goTo and the above-mentioned events is history. PlaceHistoryHandler listens to events on both sides and either updates the history (through the Historian) or updates the places (through PlaceController's goTo). The PlaceHistoryMapper maps between both worlds. The default implementation of the Historian (DefaultHistorian) uses com.google.gwt.user.client.History and com.google.gwt.user.client.Window#addWindowClosingHandler. You could provide your own implementation that uses HTML5's pushState and onpopstate for instance.
See:
http://blog.ltgt.net/gwt-21-places/
http://blog.ltgt.net/gwt-21-places-part-ii/
http://blog.ltgt.net/gwt-21-activities/
http://blog.ltgt.net/gwt-21-activities-nesting-yagni/
Is there an existing library that automatically creates a Java Swing form from a Properties (or Properties-like) object? i.e. shows 2 columns, as many rows as there are properties, properly justified Property names on the left, JTextFields for the values on the right.
I do not have access to the property names (or expected types) at compile time.
In addition, the solution must allow some value fields to be set read-only after construction.
A great solution would :
allow some property values to be specified as sensitive, requiring a JPasswordField
provide input format checking, e.g. against an object type (such as URL, Double, etc)
or by type-sensitive so that appropriate widgets (or buttons to bring up appropriate widgets) are used instead of JTextField for standard object types. e.g. JFileChooser for properties expected to be of a File type, SwingX Colour/Date selection, numerical format checking)
Getting into type-specific properties starts to sound like JavaBeans. I'd rather not go down the JavaBeans route unless there is a really easy - not a big framework - solution for this for an object that is a Javabean.
(I already know how to manually do this and could write a simple implementation myself that ignores sensitivity/type information - anyone answering along those lines will be shot down! I only want to know if such a beast already exists, preferably in a well maintained library)
UPDATE: related to Java Beans - creating an inspector window
No such thing exists. However, I wrote a rudimentary feature (and released it OSS) for https://github.com/fommil/zibaldone
We use JIDE, which not open-source.
If you don't mind that, take their Property Grid for a spin - it seem to match all your requirements.
I'm sure there are a lot of methods, but what's the recommended way to do this that has the least amount of impact to your code?
The obvious is that you create properties files, but how do you swap the values in the rendering? In J2EE you always just re-render the whole page so it's easy. But in Swing apps, do you just add the code for the .getProperty() in the paintComponent(Graphics g) method?
If that's the case, doesn't it seem heavy since now you'll have to override this method everywhere where before you didn't need to...
Additional: How do you setup a notification system to re-render all currently visible components without forcing some kind of registration pattern?
I guess if I overwrite paintComponent(Graphics g) all I have to do is fire an event that something has changed and the paintComponent(Graphics g) method will be called...
As far as I know, some applications use layout/component builders (advised by Karsten Lentzsch, and part of JGoodies API). These builders include the code to localize components (using ResourceBundle under the hood).
Other people (me included) prefer resource injection; this is normally the least intrusive method. This is the way chosen by the Swing Application Framework (JSR-296) and other GUI frameworks like Guts-GUI.
You may also want to take a look at this question which is quite similar to yours.
Regarding changes of language "on the fly" (Locale change notification), I think it is easier to implement when using resource injection (I have implemented this in Guts-GUI already, Swing Application Framework may also have it but I am not sure about it).
Java offers no way to listen to Locale changes, hence you have to create you own "Locale service" (which any Locale change request should be addressed to). In this service, you would have to enumerate all visible windows (this is possible with Window.getWindows(), no need to register visible components before) and then inject resources again.
If you want an example, take a look at the resource package in Guts-GUI source code:
ResourceInjector shows resource injection and method to change Locale, which sends a notification event (uses an Event Bus for that, but simple listeners would be fine too) about this change
WindowController listens to Locale change events
The interesting code for updating all visible windows is copied hereafter:
for (Window window: Window.getWindows())
{
if (window.isVisible())
{
injectResources(window);
window.repaint();
if (window instanceof RootPaneContainer)
{
((RootPaneContainer) window).getRootPane().revalidate();
}
}
}
Supporting dynamic language changes is a tricky problem. The simplest solution is to organise your UI in such a way that you can recreate any visible panels. That avoids the need to register or update components, when the language changes you simply recreate the view.
Obviously you lose the state of all visible components which may be an issue - but that is usually the same in a web app when the page is refreshed.
Java 6 SE allows you to reload resource bundles on the fly.
Just call the clearCache() static function of the ResourceBundle class.
Then call getBundle () again.
See this article under Cache Controls
The only solution I came up with was to create a massive registry of all components that would need to be re-rendered. Then if a call is made to switch Locale you can just call the registry and it will go through all the registered components and adjust their values. So for example for all the registered JLabels it will do something along the lines of
for(JLabel specificJLabel : REGISTRY.registeredJLabels)
{
String localeKey = specificJLabel.getActionCommand();
specificJLabel.setText(ResourceBundle.getString(localeKey));
}
where the Locale key is stored in the components ActionCommand. Then whatever screen is currently being rendered, the main parent panel is responsible for re-rendering it. Also this way the registry doesn't have to manage the Locale keys, these are completely decoupled from the registry. Each component is responsible to manage it's own Locale Keys to the ResourceBundle.
What you need is a ResourceBundle that allows you to have properties file based on Locale that you just access like a properties file.
Here is a sample on how to do it