Reputation: 37
I am trying to make an animation by Java but having trouble understanding the DoubleBufferImage and DoubleBufferGraphics. I understand about the update(), render(), and paint() sequences. However, In the methods of each, I can't understand how it is being drawn. Here are the codes.
gameUpdate() // I will just skip the updating part because I first need to understand the background.
gameRender()
private void gameRender() {
if (DoubleBufferImage == null) {
System.out.println("The Image is null: Error occurence");
DoubleBufferImage = createImage(P_WIDTH - 15, P_HEIGHT - 15);
}
DoubleBufferGraphic = DoubleBufferImage.getGraphics();
DoubleBufferGraphic.setColor(Color.LIGHT_GRAY);
DoubleBufferGraphic.fillRect(0, 0, P_WIDTH, P_HEIGHT);
DoubleBufferGraphic.setColor(Color.BLUE);
DoubleBufferGraphic.setFont(font);
DoubleBufferGraphic.drawString("Average FPS/UPS: " +
df.format(averageFPS) + df.format(averageUPS), 10, 10);
}
paint()
public void paintScreen() {
Graphics g;
try {
g = this.getGraphics();
if ((g != null) && (DoubleBufferImage != null)) {
g.drawImage(DoubleBufferImage, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
}
There's also paintComponent method which is overrided from Jpanel.
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (DoubleBufferImage != null) {
g.drawImage(DoubleBufferImage, 0, 0, null);
}
}
Here's my question. The running goes as update -> render -> and painting However as you can see from the render, they used graphics to draw. But is it all drawn in DoubleBufferImage? Is Image instance similar to panel instance? I mean, is it just addable to the frame? As this is the Double Buffering system, I want to know which methods is drawing directly, and which one is the method that draws beforehand. Finally in the running, there is no code that it's the Image or Graphics that we made are going to be added to the panel. I just want to know the timing that the BufferedImage is being drawn. Please help! I can't upload the whole code so I'm not sure if u guys can understand :(
Upvotes: 2
Views: 97
Reputation: 347334
Okay, so you seem to be banging against some misinformation and misunderstandings. Perhaps you should start by having a look at something like paintComponent() vs paint() and JPanel vs Canvas in a paintbrush-type GUI
In AWT/Swing there are at least two ways of performing custom painting, each with there pros and cons.
You could use paintComponent
, which a "hook" into the painting system used by Swing. Swing makes use of a "passive" rendering system. This means you don't have control of when something get's painted, the paint system makes those decisions and then calls (indirectly) the paintComponent
of your component so you can perform the updates.
The other mechanism (BufferStrategy
) uses a "active" rendering system, which gives you complete control over when painting occurs.
As a general rule, you can't mix them. Swing has it's own painting system and won't play well with BufferStrategy
, so that means if you want to use Swing components as part of your output, you can't.
But that won't answer your question, or not directly
Let's try and break it down
gameRender
private void gameRender() {
if (DoubleBufferImage == null) {
System.out.println("The Image is null: Error occurence");
DoubleBufferImage = createImage(P_WIDTH - 15, P_HEIGHT - 15);
}
DoubleBufferGraphic = DoubleBufferImage.getGraphics();
DoubleBufferGraphic.setColor(Color.LIGHT_GRAY);
DoubleBufferGraphic.fillRect(0, 0, P_WIDTH, P_HEIGHT);
DoubleBufferGraphic.setColor(Color.BLUE);
DoubleBufferGraphic.setFont(font);
DoubleBufferGraphic.drawString("Average FPS/UPS: " +
df.format(averageFPS) + df.format(averageUPS), 10, 10);
}
At this moment in time, DoubleBufferImage
seems to be a BufferedImage
, so when gameRender
is called, it checks to see if a buffer exists and creates it as needed. It then takes a reference of the DoubleBufferImage
s Graphics
context and prepares it for rendering, cleaning off what was previously painted to it.
Graphics
Graphics
is an abstract layer over the top of the underlying rendering pipeline, often implement using either OpenGL or DirectX depending on the system. It provides a common layer onto which graphics operations can be performed in a system independent manner
paintScreen
public void paintScreen() {
Graphics g;
try {
g = this.getGraphics();
if ((g != null) && (DoubleBufferImage != null)) {
g.drawImage(DoubleBufferImage, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
}
This worries me, as I have no context, but this.getGraphics()
seems to be taking a reference of a component's Graphics
context and drawing the DoubleBufferImage
to it.
This is dangerous and ill advised. getGraphics
returns a snapshot of the component from when it was last painted, which could be painted over at anytime when the component is painted again.
You should, at the earliest opportunity, get rid of this method.
paintComponent
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (DoubleBufferImage != null) {
g.drawImage(DoubleBufferImage, 0, 0, null);
}
}
As mentioned above, paintComponent
is the preferred method for hooking into the paint system of Swing. All this does is paints the DoubleBufferImage
it, although it should actually read g.drawImage(DoubleBufferImage, 0, 0, this);
Basically, it's an ill-advised attempt to perform double buffering in Swing ... which is already double buffered by default.
However as you can see from the render, they used graphics to draw. But is it all drawn in DoubleBufferImage? Is Image instance similar to panel instance?
No. A component is an object, which has a number of properties. One of it's jobs is to paint it's state, which is done via the various paint methods, which is passed a Graphics
context which is attached to a native peer and eventually will be rendered to the screen (or printer).
A BufferedImage
is just that, an image. The Graphics
context is just a simple means by which you can paint to it. It can then be saved to a file or, as is the case here, painted to a component (via it's Graphics
) context.
As I said above, Graphics
is just an abstract layer, which allows you to perform painting operations to a number of different destinations, screen, printers, images, etc...
I mean, is it just addable to the frame?
No. It's not a component based class
As this is the Double Buffering system, I want to know which methods is drawing directly, and which one is the method that draws beforehand.
paintComponent
and (the ill-advised) paintScreen
are painting the image directly to the component, which will, eventually be rendered to the screen by the painting sub system.
Upvotes: 1