I have started trying to create normal MVC Swing components. I have no problems with M and C, but V had thrown at me one problem which I cannot normally solve.
The problem is: Controller is main class of the component (MyComponent, for example), and it extends JComponent. View is ui delegate (MyCompanentUI) extended from ComponentUI class. All what delegate does is adds JTextField in MyCompanent and provides data binding between MyComponentModel and this field. It works just fine. But how I can bind events from JTextField to MyComponent?
If user wants to handle some events he adds listeners to MyComponent, but all real events (mouse, focus, keys, etc.) intercepted by JTextField, about which user does not really knows.
So is there any normal way to do this, except catching events and translate it to original component by hands? Or is there another way to create delegate and I just really do it all wrong?
UPD:
Thanks for your response, trashgod.
But I had something different in my mind. I was talking about something like "events inheritance", like in the case of "inheritsPopupMenu" method. So that then key, focus or mouse event happens to the component one does not process it itself, but directly transfer it to parent component. But it seems impossible, because I have noticed JSpinner has exactly the same issue - you cannot get almost any event notification from this very component.
If you are writing your own JComponent subclass and want to allow for custom UI delegates, I'd start with Kirill Grouchnikov's How to Write a Custom Swing Component.
If you are writing a composite that includes an existing JComponent subclass, such as JTextField, see if you can leverage the existing Action instances described in How to Use Key Bindings. ScrollAction is an example. You can learn the names of such actions from the component's source(s) or using #camickr's handy utility seen in the article Key Bindings.
Related
I'm refreshing my knowledge of Java by looking through some of the java tutorials. On this page I saw the addHierarchyListener and removeHierarchyListener method.
I've searched the API and google and this website. All I got was this:
Adds or removes the specified hierarchy listener to receive hierarchy changed events from this component when the hierarchy to which this container belongs changes. If listener l is null, no exception is thrown and no action is performed.
~Java Tutorial
And the API notes the listener:
The listener interface for receiving hierarchy changed events. The class that is interested in processing a hierarchy changed event should implement this interface. The listener object created from that class is then registered with a Component using the Component's addHierarchyListener method. When the hierarchy to which the Component belongs changes, the hierarchyChanged method in the listener object is invoked, and the HierarchyEvent is passed to it.
Hierarchy events are provided for notification purposes ONLY; The AWT will automatically handle changes to the hierarchy internally so that GUI layout, displayability, and visibility work properly regardless of whether a program registers a HierarchyListener or not.
~JavaAPI#HierarchyEventListener
And Later On the events:
Hierarchy events are provided for notification purposes ONLY. The AWT will automatically handle changes to the hierarchy internally so that GUI layout and displayability works properly regardless of whether a program is receiving these events or not.
This event is generated by a Container object (such as a Panel) when the Container is added, removed, moved, or resized, and passed down the hierarchy. It is also generated by a Component object when that object's addNotify, removeNotify, show, or hide method is called. The ANCESTOR_MOVED and ANCESTOR_RESIZED events are dispatched to every HierarchyBoundsListener or HierarchyBoundsAdapter object which registered to receive such events using the Component's addHierarchyBoundsListener method. (HierarchyBoundsAdapter objects implement the HierarchyBoundsListener interface.) The HIERARCHY_CHANGED events are dispatched to every HierarchyListener object which registered to receive such events using the Component's addHierarchyListener method. Each such listener object gets this HierarchyEvent when the event occurs.
~JavaAPI#HierarchyEvent
My understanding of hierarchy outside of Java is that they specify when one thing is above another etc. Like Maslow's Hierarchy of needs (some needs are above others in importance). So I know what the word means, but what does it mean for a component to belong to a hierarchy? Is it 'owned' by another component, or is one the parent?
THe only event out of added, removed, moved, or resized I can envisionage happening at runtime is the resizing event...but when would this matter?
Would an example be of a JFrame being resized, and then via a HierarchyEvent telling a JPanel to change the layout to fit the new size?
Could someone help explain them?
Right now, when I have a form with many JComponents, mainly JTextFields, JTextAreas, JComboboxes, JCheckBoxes and JButtons and want to control their behaviour, for instance the change of focus after a certain key was released, I do the following:
I put all my components in a JComponent[] and cycle through it, adding the appropriate listener. When an event is registered by said listener, I check with "instanceof" what kind of JComponent fired the event and assign the proper reaction.
I use this method for instance to cycle with VK_ENTER through the form, or to "firePropertyChange(..)" after a DocumentListener fires, or to add UndoRedoListeners and so on.
My question : is there a better way to do this and if yes, can you explain to me the benefits ?
but my question refers to the general practice of putting all
JComponents in an array and cycling through them for every listener
and every fired event. It works fine enough, but it feels a bit
"uneconomic",so I wanted to know if it is recommended practice, or if
there is a better way of doing it.
I usually write a custom listener (often as an anonymous class) per type/ instance if I have type/ instance specific behavior so that I can avoid instanceof and other other checks.
You'll want to customise the focus tranfersal system.
Take a look at How to Use the Focus Subsystem, in particular Customizing Focus Traversal
When we implement Listener, Renderer or Editor, inside methods how Java its calling automatically?
Code:
Class A implements ActionListener{
A(){
//bla bla
//bla bla
this.addActionListener(btn);
}
public void actionPerformed(ActionEvent e){**// How actionPerformed method called //automatically if we register button**
}
}
How its calling actionPerformed method automatically after registering button object? We are just passing the btn object into addActionListener(btn). How inside its calling that method?
I checked through netbeans inside addActionListener method*. There is no calling method of actionPerformed method. Also if we register it keeps on working. Is it calling by thread anywhere inside? But i checked source code. nothing is there. How?
Events are dispatched from an EventListenerList, owned by the parent JComponent, using a convention outlined in the API and discussed here. Editors and Renderers are evoked by the owning view component.
Addendum: Can we create interface same as it is? How?
Yes, JFreeChart is a fairly accessible example. Although a chart is not itself a JComponent, it uses the same model for its own events.
In Java, anything which happens upon any windows component is dealt with by the Event Dispatcher Thread:
The event dispatching thread (EDT) is a background thread used in Java
to process events from the Abstract Window Toolkit (AWT) graphical
user interface event queue. These events are primarily update events
that cause user interface components to redraw themselves, or input
events from input devices such as the mouse or keyboard.
Whenever you click or do some event, it is the EDT which kick starts the action listener, which is why doing any Thread.sleep in your action listener will eventually freeze the UI for a period of time.
Since your class implements a given interface, your class will guarantee the EDT that it will have a series of methods which the EDT can use to do whatever it needs.
For more information on the EDT, please take a look at this Oracle document.
It's magic.
Event handling is taken care of for you by the AWT API. These events are then queue and dispatched to the various components (via a serious of steps). Each interested party then handles those requests that are of interest to them before passing them up the food chain till it reaches you.
The question is, should you care?
In some respects yes, but do you care how electricity works or just that you can turn on the light switch?
I'm sure there's better documentation, but you could take a look at http://docs.oracle.com/javase/1.3/docs/guide/awt/designspec/events.html for starters...
Swing calls your ActionListener automatically when the action occurs. The actual method call is located deep inside the source code of Swing.
I have a SWING GUI class that instantiates a custom JPanel for a portion of the display. This custom class has buttons and textfields and etc. My GUI class that owns the custom JPanel also has a controller class that handles the modification of the my data models. How can I pass actions from the custom panel to it's owner (my gui class) to handle the events?
I've had the thought that perhaps I can add to my constructor of the custom panel a reference to my controller class in the gui so that I can then set it as the actionListener on my buttons. Is this approach advisable? Is there a better approach?
Your View code (your custom JPanel) should have a Controller field (or some other way of obtaining your controller class). That way when you receive an action from the user - e.g. a mouse click on a button - you can call controller.doTheAppropriateAction(). Either pass the Controller in at construction, or use a Javabean setter pattern on it, and set it just after construction in your start-up logic (which sounds like your "GUI class"). I prefer the Javabean pattern, because GUI Editors need no-parameter constructors.
You should register your View as a Listener to the relevant Controller (or Model) classes, so that you will automatically be told when anything changes - so you can repaint() your Components (or do something more advanced). That will involve setting up your own interface (for the View to implement) and listener handling logic in the Controller (or Model).
Lombok PG takes the boilerplate out of the latter.
akf gives an alternative: register your Controller as an ActionListener to your View code. The advantage of that approach is that your View code will not be tied to a specific Controller - but the disadvantage is that your Controller will be tied to your View code. I tend to re-use Controller code for different UI implementations (e.g. Swing, GWT, JSP) so my Controllers and Models are never dependent on any particular View or atomic user action.
You can pass a reference to your parent GUI as an ActionListener to your custom panel. Your custom panel can then register your ActionListener-implementing parent class with all of your buttons, etc.
Your parent class would then get notified on each action.
I'm building my first Swing app and am trying to figure out how my JDialogs - exclusively invoked when the user selects a JMenuItem - can update the components in the main client area of the JFrame which is the parent "window" of the whole app.
This is the design I've come up with, but don't know if its: (1) just plain bad, (2) not the standard (thus best) way, or (3) if I'm totally off-base here. Any suggestions are enormously appreciated.
Basically, the user selects a JMenuItem, which launches a JDialog. The user interacts with the components on the dialog, and then clicks "Done". If everything validates, the JDialog closes, and I want the parent window (a JFrame) to have its state updated (and eventually rippled out into its components).
My design:
Have an AppStateController that is a member of the JFrame subclass (my application). I would then create an AppStateChangeListener and AppStateChange EventObject subclass so that whenever a dialog validates and closes, it fires an AppStateChange event. Since the parent JFrame is the only registered listener to that event, I could define a handler that gets the event passed to it. I would make sure the AppStateChangeEvent had enough metadata to describe all the possible changes.
In theory, I like this approach: it should be clean and free of "spaghetti"-type calls to multiple controls every time a different event fires. However, I fear it may be overkill.
What do best practices dictate here? I'm not really a GUI person!
Java has several ways to implement the observer pattern; several are discussed here.
The mechanism prescribed by EventListenerList is probably the most general, as it would allow you to define your own event and listener types, and it is familiar to Swing programmers. Instead of making the JFrame a listener, let the highest level JComponent do so. Each instance of JComponent has a suitable protected member, listenerList.
Bound Properties are also an excellent choice, as shown here.
If you go with Observable, you'll need to use a delegate.
Addendum: As concrete examples, jfreechart uses the EventListenerList scheme to manage chart, dataset and series events. In contrast, jcalendar uses bean properties to notify listeners of widget selections.