I'm new to graphics in java and am having difficulty grasping the whole concept of drawing all your graphics from one method (paintComponent ()). I was just curious to see if we can draw graphics outside the paintComponent. Is that even possible? is it possible to write a line in the main method like:
fillRect(100,100, 500,400);
and have it draw a rectangle?
If it is possible, is it conventional according to Java?
Basically, I'm asking if you can draw graphics outside the paintComponent class and is it conventional.
You can draw to a BufferedImage, but if you want it drawn on the screen then generally, you'll need to use paintComponent. You can pass the instance of Graphics which is passed into paintComponent to other classes which can do more complex operations, but you should never maintain a reference that instance or try painting outside of a paint cycle context.
See Painting in AWT and Swing and Performing Custom Painting for more details
If you need more control over the paint process you could also use a BufferStrategy
See BufferStrategy and BufferCapabilities for more details
Things you should know:
Swing uses a "passive rendering" approach, this means that painting occurs when the paint system decides it needs to be done. This is why you MUST perform your painting within the context of a paint cycle (ie - in the paintComponent method)
BufferStrategy uses a "active rendering" approach, which gives you complete control of the painting process, but it's not capable of painting Swing components
Related
so when i try to create a paint method i.e.
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
}
my JFrame window will go completely black when I run my program. If I remove the paint method from the code, my normal images will appear in my JFrame window. I know FOR SURE that I am not using a .paint() method anywhere else in my code because I just added this method to my code now. Does anybody know why this is happening?
update, I am using eclipse
Start by taking a look at Performing Custom Painting and Painting in AWT and Swing to be better understand how painting works in Swing.
Basically, the paint subsystem is calling your paint method as required, when it decides that the component needs to be updated.
Because you've overridden it to basically do nothing, then nothing is painted.
As a general piece of advice, you should avoid overriding paint of top level containers like JFrame, because they are actually composite components. That is, they are actually made of a series of layers which the UI is built on
See How to use root panes for more details, but basically...
I am wondering whether I am able to use the paint method of Java's graphics class on something other than a JFrame--that is, no JFrames allowed. Is it possible?
Thanks in advance!
Graphics represents a graphic context, i.e. something you can draw on. In addition to GUI components like JFrame, JPanel etc. providing getGraphics() to access the visible gfx context, another common class that allows access to a gfx context is BufferedImage (or Image classes in general).
While painting on a visible GUI element immediately shows the results of the painting, using a BufferedImage allows you to perform the painting off screen into a buffer, and then painting the whole image at once (on a JFrame as you still need something visible) when you're ready to display the image. This is often used in animation and games when you need to avoid flickering for example.
im making a java swing game. I heard that swing components don't use active rendering(you can only override paint methods), and for that reason, i have been using BufferStrategy with Canvas. Now i have discover the getGraphics() method from JComponent and JPanel. If we can do active render in swing components, why game tutorials still override paint() and paintComponent()?
Don't EVER use getGraphics, it can return null and is nothing more the a snap-shot of the last paint cycle.
Anything you paint to it will be removed on the next paint cycle. In Swing you DON'T control the paint process and a paint cycle could be initiated for any number of reasons, many of which you don't have control over or would notified of (other then when paint was called)
The basic answer is, if you want control over the paint process, you MUST use a BufferStrategy or implement you own off screen drawing routines. There is NO means by which you can achieve a true active painting process within the Swing API, you can fake it to a certain extent, but Swing will still be able to perform it's own painting cycles when it sees fit.
Have a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing
The paint method:
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.
This method actually delegates the work of painting to three protected methods:
paintComponent, paintBorder, and paintChildren. They're called in the order listed
to ensure that children appear on top of component itself. Generally speaking,
the component and its children should not paint in the insets area allocated to the
border. Subclasses can just override this method, as always. A subclass that just
wants to specialize the UI (look and feel) delegate's paint method should just
override paintComponent.
Parameters:
g the Graphics context in which to paint
public void paint(Graphics g)
I've read many times not to override paint(), but to override paintComponent() instead. As seen above, the documentation also suggests to override paintComponent() if you want to specialize the UI.
So, I wanted to trace through the code to see why this is so.
protected void paintComponent(Graphics g)
{
if (ui != null)
{
Graphics scratchGraphics = (g == null) ? null : g.create();
try
{
ui.update(scratchGraphics, this);
}
finally
{
scratchGraphics.dispose();
}
}
}
There are many methods to trace through, but for conciseness, here's update():
public void update(Graphics g, JComponent c)
{
if (c.isOpaque())
{
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(),c.getHeight());
}
paint(g, c);
}
An overloaded version of paint() is called, and paint(), itself, calls paintComponent(). So, I guess I'm just trying to figure out what's going on here exactly. I'm very new to Swing; there are a lot of classes and it's pretty difficult to trace through all of them, especially with my limited knowledge of using GUIs, in general.
Are these methods constantly calling each other, thereby giving the illusion of an image on the screen? If so, why does it matter so much if you override paint() instead of paintComponent? I imagine that my logic is in some way flawed or lacking, considering that for applications, the documentation advises against invoking paint() directly, and instead suggests to invoke repaint(). So, basically, I'm just trying to get some insight into the overall relationship between paint(), paintComponent(), repaint(), etc.
Firstly take a look at...
Performing Custom Painting and
Painting in AWT and Swing
The second should be compulsory reading for all Swing developers.
paint is (within the context of this question) the top level method called (update is actually called first, which just forwards to paint) when the RepaintManager wants a component to be painted.
paint is responsible for (amongst other things) calling paintComponent, paintBorder and paintChildren. If you're not careful you could compromise your components ability to paint. So if you HAVE to override paint, make sure you are calling super.paint.
It's important to note, the if a child component is updated, the parent component may not be repainted, so it don't try and use paint to provide overlays for your component.
paintComponent is responsible for painting the "background" of the component. This basically delegates to the look and feel.
In the case of something like JPanel, it will fill the background with the background color (if set to opaque). In the case of something like JTable, it will paint the rows, columns and cell values.
It is very important to ALWAYS call super.paintComponent, especially when dealing with transparent components.
repaint will make a request to the RepaintManager which may consolidate the paint requests so as to reduce the actual number of paint events that are raised. This helps improve performance.
The important thing to note here is that you don't control the paint process, so don't try, work with it instead.
Your paint method is also expected to run quickly, so avoid time consuming operations, like loading resources, or compound loops where possible. If you can, create backing buffers and paint those instead
ps- Paint is fun ;)
I have been working on Java Swing for a while. I paint something(draw some basic shapes like circle,rectangle etc) on a JDesktopPane and once I resize the frame window that contains jDesktopPane or drag some other window over this frame, then the drawn shapes disappear. I use an object of the BufferedImage class so as to save the image. So Is there any way of preventing the shapes getting disappeared or repaint it when they disappear?
You need to make sure you are saving what you paint and repainting it each time in the paintComponent() method. This method is called automatically whenever a repaint is needed (for example: because of a resize).
I can only provide a guess since you've decided not to post the necessary code, but my suggestions are:
Don't get your Graphics object by calling getGraphics on a component. Instead,
Be sure to do your drawing in a class that subclasses a JComponent or one of its children (such as a JPanel).
draw your BufferedImage in the JComponent's paintComponent method immediately after calling super.paintComponent() in the same method. Use the Graphics object that is provided by the JVM and passed into the method's parameter.
To be sure that your paintComponent method's signature is correct, place an #Override annotation immediately before it. Otherwise if it is not correct, the JVM will probably not call it when you expect it to.
But also, please when asking a question here, try to give us enough information so we don't have to guess. Since your problem is graphics related, it would make sense to post your graphics-related code, right?