I have a JPanel which contains a lot of child components. While updating\adding new components to the parent JPanel I'd like to prevent it from repainting, how can this achieved?
Try RepaintManager.currentManager(component).markCompletelyClean(component). It will prevent the component from repainting. You might need to do this after each time you add new components.
setVisible(false)
update
setVisible(true)
you could try by using setIgnoreRepaint(boolean value) but it's a typical swing feature that can or cannot work (mainly because it depends from AWT so you never know).
Otherwise you could override the paint method by using a flag that simply makes the methor return without calling super.paint(). (actually overriding paintComponent should be the right choice)
Related
I always do
Jbutton.setEnabled(false);
Jbutton.update(Jbutton.getGraphics());
when disabling a button, but someone told me that Jbutton.update(Jbutton.getGraphics()); shouldn't be used, or at least not used that way. Why? is it not efficient? Is it incorrect? Should I change my method?
Shouldn't use getGraphics() on Jbutton.update,
Actually it's wider than that. Programmers should never use getGraphics on any JComponent (or AWT Component) or the same for Swing (and AWT) windows.
Why?
Because the painting methods are called by the API, whenever it feels the need to repaint (e.g. restoring a window from minimized, moving another window on top of or away from the window, bringing it to front ..).
So any call that uses getGraphics is 'transient'.
[ The correct way to do custom painting is mentioned in Holger's comment, but that wasn't the question. ]
I've seen it written on this site a number of times (such as here, and here) that you mustn't call setVisible(true) before adding components to a JComponent, but I haven't seen an explanation, and information on the internet seems scarce.
Why is this the case, and what happens if you break the rule?
You're not breaking anything if you call it first, but you will probably then need to call it again if you've added anything. Else Swing won't render the added components. You need to have the JVM call the JFrame's paint(...) method to have the JFrame's components rendered, and setVisible(true) will ask the JVM to do just this. If you've ever add components after calling setVisible(true) and don't see the components, you'll find that they'll "materialize" if you re-size the JFrame. This is because re-sizing it causes the operating system to ask Swing to repaint the GUI, and this will result in paint(...) being called.
Note that if you add a component after creating your GUI, you can call revalidate() and often repaint() on its container to get the new component laid out correctly and then rendered. The repaint() will definitely be necessary if the change in components involves a deletion, or a component being drawn where another component was visualized previously.
A book suggestion that I highly recommend: Filthy Rich Clients buy Guy and Haase. Just buy it! You won't regret the purchase.
Amplifying on #Hovercraft's helpful analysis, you may also have to re-pack() the enclosing top-level container. This example, which adds elements to a JList after setVisible(), may illustrate the trade-offs.
Fred Swartz writes in a note on Java GUI programming (more specifically, about the best ways to access and use a component's ContentPane)
... if we get the predefined content pane [by invoking
getContentPane() on a JFrame], it turns out it's actually a
JPanel, but we really can't take advantage of the functionality that
was added by JComponent.
-- http://www.fredosaurus.com/JavaBasics/gui/gui-commentary/guicom-60-contentpane.html
In this case, what prohibits someone from using the JComponent functionality of a JPanel? JPanel extends JComponent, so shouldn't JPanel have unhindered access to JComponent's methods?
Read further in his comments about using the returned Component:
If we downcast it to JPanel, we create fragile code that might break because the contract with getContentPane() is to return a Container, and there is no guarantee that future versions will actually continue to return a JPanel.
I've seen it written on this site a number of times (such as here, and here) that you mustn't call setVisible(true) before adding components to a JComponent, but I haven't seen an explanation, and information on the internet seems scarce.
Why is this the case, and what happens if you break the rule?
You're not breaking anything if you call it first, but you will probably then need to call it again if you've added anything. Else Swing won't render the added components. You need to have the JVM call the JFrame's paint(...) method to have the JFrame's components rendered, and setVisible(true) will ask the JVM to do just this. If you've ever add components after calling setVisible(true) and don't see the components, you'll find that they'll "materialize" if you re-size the JFrame. This is because re-sizing it causes the operating system to ask Swing to repaint the GUI, and this will result in paint(...) being called.
Note that if you add a component after creating your GUI, you can call revalidate() and often repaint() on its container to get the new component laid out correctly and then rendered. The repaint() will definitely be necessary if the change in components involves a deletion, or a component being drawn where another component was visualized previously.
A book suggestion that I highly recommend: Filthy Rich Clients buy Guy and Haase. Just buy it! You won't regret the purchase.
Amplifying on #Hovercraft's helpful analysis, you may also have to re-pack() the enclosing top-level container. This example, which adds elements to a JList after setVisible(), may illustrate the trade-offs.
I am currently trying to build an expanding panel in Swing (akin the WPF's Expander control) and I'd like to retain the usual methods for manipulating it (i. e. setLayout, add, etc.). Only they should be routed to an embedded panel (the one being shown or hidden).
How would one do that? Overriding every method of JComponent and re-routing that to an embedded JPanel would be cumbersome, but that's the only way I see.
Or should I rather make the embedded panel visible to the outside and force users to use something like ExpanderPanel.getInnerPanel() instead. But then it's no drop-in replacement for JPanel which I think would be nice to have.
Take a look at the JXTaskPane from Swingx project. It already does what you need.
In 1.5(ish) Swing routed a few methods to the content pane in JFrame, JApplet, etc. Whilst there appeared to be some usability benefits for those just starting, it doesn't actually fix the problem. So everyone has to deal with a very strangely behaving API. So my advice is to avoid this approach.
If you have a Container widget which holds a panel you want to show and hide, why not layout your inner panel however you want, then add it to the Container panel, then use static methods against the Container to say
JPanel p = new JPanel();
//do something with the JPanel...
ContainerWidget.setContent(p);
ContainerWidget.expandPanel(p,true);
Would somethign like this work?