A quick question,
Is it necessary to call revalidate() method each time, you change the location of components?
And what are other instances, when it is necessary to call revalidate() method?
Every time you create or modify (location, size or internal content) or remove a component or multiple components, it tells the layout manager the new component list.
Yes, once you change the location, it is necessary to call revalidate().
Is it necessary to call revalidate() method each time, you change the location of components?
You should not be setting the location of components. That is the job of the layout manager.
The point of using revalidate() IS to invoke the layout manager so the size/location of the components can be determined based on the rules of the layout manager.
So you invoke revalidate() and typically repaint() AFTER you add or remove components from a visible container.
Related
I'm trying to understand when to use revalidate/repaint/pack.
Surprisingly I haven't found much detailed under-the-hood documentation (feel free to link).
So far I have understood that this is all the responsibility of the RepaintManager.
paint/repaint refer to what sees as dirty/clean
pack/validate/revalidate refer to what is valid
This article on Oracle explains that calling a repaint enqueues a job on the Event Dispatcher Thread that will in turn call paintImmediately() on the component (this redraws the component).
This trail indicates that to be or not to be valid is associated with the LayoutManager. And that this is all about the size of the component rather than the content.
Is it true that you should call revalidate when you move/resize your component and repaint when you change it's contents?
Is the pack() method really a deprecated thing that you should never call?
Are any of the above claims wrong?
Here are a few basic cases where you need to invoke those methods (I cover the basics but I may have missed a few other cases where calling those methods would be required).
You should call revalidate() on a container when you have either: added one or more component, removed one or more components, changed the constraints of one or more contained components (constraints or XXXSize(), although the latter is not recommended), changed the LayoutManager of the container.
You should call repaint() whenever you want that component (and its descendants) to be repainted. Eventually, this will call paintComponent() (for basic widgets this will delegate to XXXUI.paint()), paintBorder() and paintChildren() (at least in Swing)
pack() actually sets the size of a window to its preferred size. You should usually call this right before making the window visible. You may call it later on but this will give a weird user experience (I don't know many applications that resize their windows once displayed)
The main advantage of using revalidate() and repaint() is that they can coalesce themselves. This means that if you call several times repaint(), the painting will only be performed once.
So I have a panel and depending upon users entry they are populated with an x number of jlabels. Now the problem is, when the user entered information the labels successfully populate but they do not display properly in the panel; they don't even show.
Only when I resize the frame they appear?
It's been a while since I did Swing programming and I am trying to remember the method which you are supposed on a container after you add components. I think it's revalidate().
usually you have to call:
JPanel yourPanel = new JPanel();
yourPanel.repaint();
yourPanel.validate();
invalidate marks a component as needing to be relaid out soon because the component or one of its children has been resized or become visible or invisible. invalidate is called on a component automatically when children components are added/removed.
validate checks that a container is valid and if not, calls doLayout or invalidateTree to calculate positions and sizes of children components. validate effectively redoes the layouts if necessary, deciding on new sizes and locations of all components in the container.
After adding/removing components from a container, validate must be called on the parent to let the LayoutManager redo the layout. Calling validate does not schedule a repaint, so you may need to call repaint after the validate.
There seems to be many methods in Java awt Container class that are related to validate. Apparently they don't do data validation. Is it useful for a Swing developer in any cases? Some of the methods:
validate(), invalidate(), validateTree(), isValid() etc.
Citing the API doc:
The validate method is used to cause a
container to lay out its subcomponents
again. It should be invoked when this
container's subcomponents are modified
(added to or removed from the
container, or layout-related
information changed) after the
container has been displayed.
Validation in a Swing context concerns requesting a component to lay-out its sub-components after one of these is modified.
For example, suppose you implement a custom JDialog with a button "Show Filters". Upon clicking this button, you might want to add an additional "filter" panel to the south of the JDialog. Upon adding the new sub-panel you would be required to call validate() on the JDialog to cause it to lay-out the new panel correctly.
I'm putting together a Swing application where I often want to replace the contents of a JPanel. To do this, I'm calling removeAll(), then adding my new content, then calling revalidate().
However I'm finding that the old content is still actually visible (though obscured by the the new content). If I add a call to repaint() in addition to revalidate(), it works as expected.
I'm sure on other occasions I've experienced that just calling revalidate() is enough.
So basically my question is - should I need to call both functions and if not, when should I call each of them?
You need to call repaint() and revalidate(). The former tells Swing that an area of the window is dirty (which is necessary to erase the image of the old children removed by removeAll()); the latter tells the layout manager to recalculate the layout (which is necessary when adding components). This should cause children of the panel to repaint, but may not cause the panel itself to do so (see this for the list of repaint triggers).
On a more general note: rather than reusing the original panel, I'd recommend building a new panel and swapping them at the parent.
Any time you do a remove() or a removeAll(), you should call
validate();
repaint();
after you have completed add()'ing the new components.
Calling validate() or revalidate() is mandatory when you do a remove() - see the relevant javadocs.
My own testing indicates that repaint() is also necessary. I'm not sure exactly why.
revalidate is called on a container once new components are added or old ones removed. this call is an instruction to tell the layout manager to reset based on the new component list. revalidate will trigger a call to repaint what the component thinks are 'dirty regions.' Obviously not all of the regions on your JPanel are considered dirty by the RepaintManager.
repaint is used to tell a component to repaint itself. It is often the case that you need to call this in order to cleanup conditions such as yours.
revalidate() just request to layout the container, when you experienced simply call revalidate() works, it could be caused by the updating of child components bounds triggers the repaint() when their bounds are changed during the re-layout. In the case you mentioned, only component removed and no component bounds are changed, this case no repaint() is "accidentally" triggered.
yes you need to call
repaint();
revalidate();
when you call removeAll() then you have to call repaint() and revalidate()
Whenever I remove and add swing components from say JPanel, shall I perform call on validate or revalidate?
revalidate() would be better. revalidate() marks all the container upto the top level as not proper or not valid. Then it calls validate() on the top level. The validate() method of the parent checks if at least one of its immediate children is signaled invalid or improper. it calls validate of the parent.
so calling revalidate() automatically means calling validate().
revalidate() is basically a invalidate() followed by a validate().
Look at Sun's Java source code.
You want to call revalidate().
At least in Java 7, revalidate() doesn't necessarily "erase" removed components from the screen. I believe that happens when the bounding box shrinks. For these cases, call repaint() after the revalidate().
I would think revalidate() is what you want. The validate() method will be automatically called for you after a call to revalidate(). See the Java API for JComponent.revalidate().