Is the setBounds() method of a Component like JPanel called on the Event Dispatch Thread? I am asking this because I am writing a program that draws platforms and uses a Swing Timer to move them up. I override the setBounds() method so that every time the JPanel is resized, the platforms will resize too. I just want to make sure that setBounds() doesn't resize the platforms while the Timer is moving them. Also, would it be better to use a WindowListener to check if the JPanel was resized?
setBounds() will be called on the EDT by Swing code, but you have to ensure your code's own invocations of setBounds() also only calls it on the EDT. If you can ensure all calls of setBounds() occur on the EDT, then you shouldn't have to worry about setBounds() being executed while your SwingTimer is being executed because SwingTimers also execute on the EDT by default (so they won't execute at the same time).
Also I never seen someone override setBounds() so I do wonder if there's not an alternative solution such as just querying the bounds every time your SwingTimer executes. Using a listener listening for window resizes like you say does sound much better.
Related
We have following methods:
java.awt.Component#repaint()
This is old method that repaints in AWT. It does not repaint immediately, it schedules repaint.
javax.swing.JComponent#repaint(long, int, int, int, int)
This is new swing method that repaints in Swing. It schedules repaint with the RepaintManager.
Both of them may be invoked from a user thread as well as from the event-dispatching-thread.
Which of them is the most correct way to repaint Swing component (JComponent)?
Which of them is the most correct way to repaint Swing component (JComponent)?
Both of them are the correct way.
Swing components always invoke repaint() when you change a property of the component by using setText(), setForeground(), setBackground() etc. This will make sure the entire component is repainted.
The repaint(...) method can be invoked if you need to optimize painting of the component. If you have a large component and only a small part of the component changes you can use this method. However, I would recommend you don't worry about this. Swing painting is double buffered and efficient so there is rarely a case when you need to optimize the painting code.
I am a novice Java programmer and I'm finding quite some difficulty in figuring out the actual difference between the functioning of the paint() and repaint() method.
Also in some of the programs that I studied I found paint() and repaint() interchangeable.
Can someone please explain the difference? Thank you
Assuming that you are referring to the void paint(Graphics g) method that is declared in the Component class:
This paint method is called automatically, whenever it is necessary to paint (parts of) the component. For example, when the window was obstructed by another window and then becomes visible again: The window manager will determine this, and call paint on the top level component (e.g. a Frame) and this call will make its way down to the actual "bottom" components (e.g. a Button). The Graphics object that is passed to this method is provided by the Window manager, and corresponds to the area on the screen where the component should be painted. (And this Graphics object is only valid during the paint method).
In contrast to that, repaint() just triggers a new painting process. It is telling the system: "Please call paint on this component as soon as possible". You can call this method manually. And you can call it freuqently: The calls to repaint are coalesced. That means that when you issue many calls to repaint in a short period of time, then these calls may be summarized and may eventually only trigger one call to paint.
The paint method should not be called directly as the javadoc states:
Invoked by Swing to draw components. Applications should not invoke
paint directly, but should instead use the repaint method to schedule
the component for redrawing.
The repaint method should be used instead if you want the component to be repainted (redrawn). The javadoc also refers to the following documentation: Painting in AWT and Swing
paint() get called automatically at runtime. If you want to call paint() manually(again) then repaint() is used.
The paint() method contains instructions for painting the specific component.
The repaint() method, which can't be overridden, is more specific: it controls the update() to paint() process. You should call this method if you want a component to repaint itself or to change its look (but not the size).
I know that JPanel is, by default, automatically double-buffered. However, I have a particularly time-intensive painting operation in my panel, but the panel only needs to be repainted when the underlying data changes, which is rare. Therefore, I'd like to reuse the JPanel buffer instead of having it clear after every call to repaint().
I've manually implemented a "dirty" flag on my JPanel subclass, but I have no idea how to cancel a paint operation once it's been started. I can't avoid the call to repaint in the first place, since my panel is inside a JScrollPane, which is being repainted every time it's resized (which does happen frequently), which causes my custom panel to be repainted.
Is there any way to do this without manually buffering the panel? If not, what's the recommended method for implementing a manual buffer in conjunction with a JPanel?
I have a particularly time-intensive painting operation .. only needs to be repainted when the underlying data changes, which is rare..
Paint the data to a BufferedImage, display it in a JLabel. Call label.repaint() if it changes. E.G. as seen in this answer.
Bonus Showing an image in a label is a way to get a GUI with a preferred size, that does not need to extend anything. To get the perfect size for the frame or dialog that displays it, call pack().
I have following code:
canvas=new MembershipFunctionComponent(functions);
canvas.setPreferredSize(new Dimension((int)this.getWidth(), (int)this.getHeight()));
canvas.addMouseListener(canvas);
pane.add(canvas);
MembsershipFunctionComponent extends JComponent. Why is paintComponent method executed 2 times?
paintComponent can get called at pretty much any time by the Swing framework. Examples of when this might happen:
Any time a component is resized
Any time part of the component is revealed (for example in a scrollable window)
Any time the repaint() method is called on your component (or possibly a parent or sub-component)
Any time there is a layout change
None of this should worry you - you should just write your code so that it doesn't care how many times paintComponent is called.
I'm a little confused about the Swing painting model.
Suppose that I have a JComponent comp, and I do something like:
c.setBackground(Color.RED);
c.setBackground(Color.YELLOW);
Obviously, the end result is that the color is yellow.
How does Swing handle this?
Does the first call trigger an immediate repaint so there'll be a short flicker of red before the yellow? Is this sequence significantly slower than just a paint of yellow?
If I was running this from outside the Swing Event thread, I would assume that in most cases (though a race condition is possible), by the time the Swing EDT comes visiting the property is already set to yellow so there'll never be any red painted.
However, my understanding is that I should make these calls from inside a Runnable in the Swing EDT. Is that correct? In that case it would seem like the EDT would have to fully perform each change without any "lookahead"?
The area of the window is marked dirty immediately. A paint request will later come back on the EDT. The OS or the event queue mechanism (or even the component) may merge repaint events (strictly a quality of implementation matter, but in practice repaints in the same window will be merged, even if they do not intersect).
Methods on Swing components should be called on the EDT. The Event Dispatch Thread belongs to AWT, not Swing.
First of all you should not make such calls outside of EDT. The results can be unpredictable.
Since all Swing components are double-buffered you will see no flicker when doing this. In addition to that all consecutive repaint requests are joined into one when possible.
Overall, you shouldn't see any issues at all when doing this as long as it is done on EDT