Well, I guess it's for listening to hierarchy changes but I don't really understand what this means in practise.
Anyone has a good real life example when this should/could be used ?
Thanks
David
I used it once.
I was building a bubble-tip(a tooltip but with an arrow pointing to a target component) component. I used JLayeredPane with POPUP_LAYER to implement it.
So whenever the target component changed it's position or resized, I wanted a notification so that i could adjust my tip's arrow to point to it. This is my practical usage of HeirarchyListener. Now why could'y have I used ComponentListener ;)?
One example would be a component that should do something (e.g. display an animation) whenever it becomes visible. Its own visibility attribute is not sufficient, since visibility is inherited. A HierarchyListener allows it to be notified when the inherited visibility status changes.
Also:
http://www.google.com/search?q=%22implements+HierarchyListener%22
Related
I have few questions about layout and paint procedures in SWT.
Fox example, I have a Composite with children. When I invoke composite.layout() what does it mean? Layout? Paint? I find confusing this phrase in the javadoc:
Note: Layout is different from painting. If a child is moved or resized such that an area in the parent is exposed, then the parent will paint. If no child is affected, the parent will not paint.
Another question is, what is going on when I set composite.setLayoutDeferred(true) and invoke after that composite.layout?
Also, what happens when I set composite.setRedraw(false) and after that invoke still the same composite.layout()?
I spent half of my day reading javadoc and doing some practice investigation, but it didn't shed any light on this problem. I can't understand the theory behind this API.
Thanks in advance.
Ok, let me try to explain this:
There are two types of Widgets involved here: Those that can have a layout (Composites and its subclasses) and the other Controls.
When a Paint event occurs, a Composite (if it has a Layout) will cause it's children to repaint. If the children are Composites as well, they will propagate this. If they are other Controls, they will repaint.
Repainting of a Control means that the "state" of this control has changed, i.e. in order to represent its stage properly, it has to do something. This can be caused by a resize event, or by hovering the mouse over it or by clicking on it, basically everything where the visual appearance has to change.
Control#setRedraw(boolean) does exactly what the JavaDoc says:
If the argument is false, causes subsequent drawing operations in the receiver to be ignored. No drawing of any kind can occur in the receiver until the flag is set to true.
The difference to Composite#setLayoutDeferred(boolean) is, that events that occur while it was set to false will be cached and they will be performed, when it is set to true again.
If you call .layout() after you call those methods with true, nothing will happen, if you call them before, the event will take place.
Invoking composite.layout() means to let the set layout manager set the child controls position. Use this if you have changed some properties of the child controls or the configured layout which will influence the layout positions (heavily depends on the layout manager).
Use
control.setRedraw(false);
// other code
control.setRedraw(true);
to improve performance if // other code performs a lot of GUI modifications which would trigger a lot of smaller repaints.
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
Is there a way to find out which component has the actual focus in a Vaadin window!?
No, at least not directly (which is surprising). Please follow the links and discussions indicated in the thread on Vaadin forum.
You can go around it, but it will require certain amount of work. A starting point is the Focusable interface. Basically, you should capture all focus events in all the components.
You can add a focusListener and a blurListener to each component. If a component has focus you set an object to the current component, if blurListener gets called you set it to null.
If the object is != null you just need to check which component it is and you know which one has focus.
I wonder if there's a good documentation (or a (viewable) ebook) about
the lifecycle of Swing components.
Is "lifecycle" the correct term, anyway?
I hope to find answers to question such as:
How, when, in which order painting methods are called?
How, when, which events are called by whom?
What is the exact sequence of method calls for component creation?
From time to time I encounter strange behavior of my apps, for example:
ComponentListener's resize event is called before setVisible(true)
(so that root pane has negative dimensions!)
Some components are laid out correctly only after resizing the JFrame by hand
Changing a super class from JPanel to JLayeredPane causes my class
to be laid out differently inside an other container.
And lot of other strange things...
I had the same question long ago.
I can't believe how hard is to find a good resource about this topic in the internet.
Fortunately I've found this link and now I have it in my bookmark with golden tag. :)
A Swing Architecture Overview
Once you have a good grasp of how they work conceptually you will be able to fix most of the problems you mention.
I hope it helps.
Here's a very specific coding question:
I've recently been asked to maintain some old-ish Java Swing GUI code at work and ran into this problem:
I've attached my own subclass of InputVerifier called MyFilenameVerifier to a JTextField (but it may as well be any JComponent for these purposes). I've overridden the verify() method such that it calls super.verify(input) (where input is the JComponent parameter to verify()). If super.verify(input) comes back false, I do:
input.setBorder(BorderFactory.createLineBorder(Color.RED));
This is a convention used throughout the UI of this application that started long before me, so I don't have a lot of choice as far as using other ways to get the users attention (wish I did). This is just the way it works.
Problem is, once the user goes back and types something valid into the text field, I need a way to set it back to default border (instead of just saying set it to Color.GRAY or whatever, which is a different color from its original border). I need a way to say, "remove the extra decoration and go back to normal" or just set the border to its default, in other words.
Couldn't you just call input.getBorder() and cache it somewhere before setting the border to red?
Or without caching anything, you could tell the JComponent to update its UI back to the look and feel's defaults via component.updateUI. That should make the component reset its colors, borders, fonts, etc to match the original settings.
input.getBorder()
Wouldn't it be awesome if no one ever saw this and I got away free without the ass-beating I deserve for asking this question?
Not sure how your system is build, but I think you can store the original border before changing it. So you can change it back later
// assuming the Border was not null before
if (!super.verify(input)) {
original = input.getBorder();
input.setBorder(...);
} else {
if (original != null) {
input.setBorder(original);
original = null; // not needed
}
}
You need to preserve the existing border when you change it.
One way to do this is to use the methods putClientProperty() and getClientProperty(), which you'll find documented in the API.
Another possibility, if there are only a few input widgets you need this for is to subclass, e.g. JTextField, add setBorderOverride() and modify getBorder() to return "overriddingBorder" if it is not null.
Then you just use setBorderOverride(redBorder) to make it red and setBorderOverride(null) to clear it.
This of course depends on the painting to use getBorder(), which it may or may not do, and which may be implementation specific.
Incidentally, you only need a single static reference to the border-- it's the selfsame border instance used by all JTextFields.