This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Java Swing revalidate() vs repaint()
Hi all
I'm fighting with my program to make it refresh at the right time.
And not having a lot of success lol
I have 2 questions
Q1: which should I use when my interface has changed: repaint or invalidate?
Q2: when should they be called? I know it sounds stupid but I'm actually having problems because of SwingWorker and other threaded operations.
Q1: which should I use when my
interface has changed: repaint or
invalidate?
If the layout is not up to date because of resizing , font change etc then you should call invalidate. Invalidating a component, invalidates the component and all parents above it are marked as needing to be laid out. Prior to painting, in the validation step if no change is found then the paint step is left out.
If there is some part of component which is being updated (defined by the graphic's clip rectangle, called "damaged" region) then you should consider calling repaint. One of the reason a damaged regions may occur is from the overlapping of a part of your component because of some other component or application.
As per my experience the repaint() is more effective if you call it on the innermost enclosing component (i.e. using public void repaint(int x, int y, int width, int height) rather than using public void repaint()).
Q2: when should they be called?
Invalidate(): marks a component as not valid -- that means, it's layout is or may not be "up to date" anymore: i.e. the component is resized, a border is added, it's font changes, etc. you should never need to call invalidate() by hand, as swing does that for you on pretty much for every property change.
When more than one region within the control needs repainting, Invalidate will cause the entire window to be repainted in a single pass, avoiding flicker caused by redundant repaints. There is no performance penalty for calling Invalidate multiple times before the control is actually repainted.
Repaint() : If the component is a lightweight component, this method causes a call to this component's paint method as soon as possible. Otherwise, this method causes a call to this component's update method as soon as possible.
Also have look at Update method.
NOTE: Swing processes "repaint" requests in a slightly different way from the AWT, although the final result for the application programmer is essentially the same -- paint() is invoked.
Refer to the link below for an excellent link on how painting is done in AWT and Swing:
http://www.oracle.com/technetwork/java/painting-140037.html
Hope this will help.
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.
For my program I have a JPane that as the game progresses it adds labels to the panel, however the only way I can make the panels show up is by using add(label) then revalidating and vice versa for removing labels.
My problem is that once it gets to the point that I have more than 40 labels on the screen the revalidate has to process too many things, so how can I override the revalidate(), ether works, so that it only revalidates the specific component that was added, and not every component on the screen. I know there is a loop somewhere within the revalidate() method that will run through a loop of all components, but I just can not for the life of me find it. I would like to be able to call revalidate(component-here) or validate (component-here) and have it only update that specific component.
I know there are other ways of writing this program but I am only interested in how to override revalidate() so no "you could have redone your whole code this way which should only take you like 6 hours >.<".
http://www.fileserve.com/file/jFdQ6nv/FINAL_PROJECT.zip a link to my eclipse project, if anyone who wants to help would like to see what im actually talking abouyt
I just tried this example. Adding 1000 text areas only takes a second, and updates are instant. Labels go even faster. You might want to look at something else slowing it down.
Also, you could look at CellRendererPane. It overrides invalidate() to do nothing.
public void invalidate() {}
Hello? anyone had a problem like: cursor blinking in more than one field at a time?
In my case the following happens: When you double click on a field JTextField, opens a JDialog, so
after closing this, the focus is directed back to the field clicked before opening the screen.
What happens is that after performing this action, two fields are flashing at the same time (usually the first field
screen, as well as the field in which efetuei double click).
This medium is random, there are cases in which it does not occur.
When debugging the inner class Handler, contained within the class DefaultCaret more specifically the actionPerformed method, realized
that: time is a field, and time is another, which are precisely the fields that are flashing (q seems obvious I know). but they are
the own inner classes of Java that are calling the method.
When passing over the field using the Tab, the cursor false, vanishes.
I'm using JDK 6
I returned the focus within the invokeLater(), but not solved. Now both synchronized flash
The first JComponent focusable is one of the fields that flashing improperly
I'm using my own FocusTraversalPolicy, does that may be influencing? The funny thing is that there is no treatment particularly strange about my class.
I noticed that the standard Java class, using a method within the Syncronized getFirstComponent(), but added the same control, but still is not ok
Actually it's Focus issue for me.
Normally when JTextComponent looses Focus setCaretVisible(false) / setSelectionVisible(false) is called and when Focus gained opposite thing happens.
After closing JDialog try to return Focus inside invokeLater(). Also check what's the first focusable JComponent in the JDialog's parent.
This situation occurs because the project I'm developing is quite large, so do not get small examples of implementation
The project has many components, Tables and Container's, which require focus through at the same time.
It turns out that Swing, put in a queue for execution, a lot of threads, and then dispatching them going, and while he did not finish running it, you can cram grabFocus() or requestFocus(), which does not cry, the first he has to finish everything and then run my request focus.
Resolved palliatively this situation, using the Swing SwingUtilities.invokeLater(...);
Thanks for the tips.
I'm trying to write an own layout manager.
Components must be placed and sized relative to each other.
This means: when the user drags or resizes an component, some other
components (but not the one altered manually by user) have to
be altered.
Swing tells the layout manager to layout the components every time when
some of them is moved/resized. This is a problem hence the layout
manager itself moves/resizes components:
It fails, the method
layoutContainer(Container parent) is called multiple times.
An example of the whole thing (simplified, in fact my layout manager does
more complex stuff):
[-component1-][-component2-------][-component3-]
user resizes component2 to be smaller, my layout manager would adjust
other components so that all of them would take same space as before:
[-component1-][-component2-][-component3-------]
here, the actions should stop, but they go on: now the layout manager
is invoked because of resizing component3
How could I achieve my intention (in an elegant way)?
Thank you.
EDIT:
Removed threading-related information after suggestions by answerers.
This kind of feedback loop is not uncommon when dealing with events. There are several approaches you can use to break out of this loop and the one I suggest you try is to keep track of the calculated sizes of the components. Then, when you handle the resize event, compare the actual size to the calculated size, and just return without doing anything if they are equal. This is probably the most robust approach as it doesn't depend on the order or frequency of the events. As stated elsewhere you shouldn't need to touch anything related to threads from your layout manager.
This isn't a thread synchronization issue.
You said that when users change the size or location of an object other objects must be altered. I'm guessing that you are listing for some kind of change event so that you can trigger a recalculation of the layout whenever the user changes an object. If so, I'm further guessing that your layout manager is triggering this event, causing it to be invoked again.
Of course, this is only speculation without reviewing your code.
I can't speak to the correct implementation of a layout manager, but as far as threading is concerned, all events in Swing are dispatched on the Swing UI thread, i.e. the same thread. Thus, synchronizing objects will have no effect because only one thread is ever involved. You can see what thread is invoking a method by printing Thread.currentThread() or inspecting it in a debugger.
Depending on what you're trying to do, you may want to take a look at miglayout. I've found it very powerful and easy to use. Correctly implementing a Swing layout manager is a non-trivial task.
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.