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.
Related
When creating an MDI Swing GUI, I have a number of JInternalFrames that are added to a JDesktopPane in a JFrame. I make these internal frames invisible by adding setVisible(false) in the constructor, after the initComponents method (as the GUI builder automatically sets these frames visible in this method).
At runtime, the user can choose to open and close the JInternalFrames by invoking listeners that call setVisible(true) and setVisible(false), depending on the current state of the frames. I like how the previous position and state of an internal frame remains intact using this design. However, something tells me this must be terribly wrong, even though I haven't seen any drawbacks yet.
So, my question is: is this poor design?
In the context of a Multiple Document Interface (MDI), this approach is quite reasonable. In addition, you can use the JInternalFrame method setSelected() to highlight a particular frame. To ease navigation, this and other methods can be used in Action, as shown here.
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.
How to get active (having focus) frame (JInternalFrame) that is inside JDesktopPane? I need it for my MDI notepad (not that anybody would use that, just a training project). Looking at api, I see only functions to get all JInternalFrames, not active one.
Use JDekstopPane.getSelectedFrame() method (From doc: currently active JInternalFrame in this JDesktopPane, or null if no JInternalFrame is currently active.) or JDesktopPane.getAllFrames() to get list of all JInternalFrames currently displayed in the desktop and check isSelected() method.
Make a List<JInternalFrame> and check isSelected() as you iterate though it.
Addendum: See also this example that uses Action to select an internal frame from a menu.
Have you looked at the Java tutorial titled How to Use Internal Frames? In your code you need an InternalFrameListener (API) (Tutorial) and listen to activate/deactivate events. Activated means the internal frame was brought to the top; deactivated means it's no longer on top. Since JDesktopPane extends JLayeredPane you can also set the z-order of components added to it.
Don't iterate over all the panes - use events.
If for some reason you prefer to poll your UI rather than use an event-driven approach you can call getSelectedFrame which returns the active JInternalFrame. I'm not sure why no one else mentioned it.
There is one method which prints layout information for particulat components. I knew one method is there but I forgot the name.
When you call that method for Swing component it displays layout information in detail for that component just like dumpstacktrace call.
Any idea? What is that method name? I read it in one book but forgot it. Or let me know some good ways to debug Java Swing layout.
When your JFrame is visible press CTRL+SHIFT+F1 and see the console output for the tree hierarchy of components and layouts.
I don't know about a specific method for this by you can do this with a key press at runtime.
Take a look at page: Troubleshooting AWT
It provides the following debugging tip:
To dump the AWT component hierarchy, press Ctrl+Shift+F1.
It also provides other tips for layout debugging under the section "Problems With Layout" and there is another section dedicated to swing "Troubleshooting Swing"
Each Container (and this includes all JComponents) has a getLayout() method which will return the layout manager that has been set for this component or null if none are set (but remember that many are given default managers). You can also getComponents() to return an array of the components held. If you want to see all layout managers, you'd have to write a recursive method to go through all the components held, check that they inherit from Container and then call the above methods.
I'm creating a custom Swing component that inherits from JPanel.
What is the right way to override/implement the various sizing methods (getPreferredSize, setPreferredSize, getMinimumSize etc.) in order to get "good behaviour", particularly with regards to:
Working with different layout managers
Behaving correctly when setPreferredSize() is called
Reacting appropriately when a border is set via setBorder()
Don't inherit from JPanel unless your component is a composite of several subcomponents. In most cases inheriting from JComponent is enough.
As far as resizing goes... override getPreferredSize, getMinimumSize and getMaximumSize methods to get an appropriate behavior in layout managers.
If your component is a composite of subcomponents in most cases preferred size is already defined by combination of your subcomponents so you don't have to override this one.
Although rather annoying: that depends, on the layoutmanager in this case. Usually the layoutmanager can best be used along with constaints to get a good layout.
I've used GridBagLayout, and after getting used to it, I found it worked pretty well using right GridBagConstraint for each component.
Sometimes a good visual ui designer can help too, like the one from Netbeans, or you could consider a paid one like Swing Designer or JFormDesigner. Can save you some time fiddling with pixels.