Drawing images on a JPanel

G

George

Dear All,

I want to draw an image on a JPanel, but without going through the
addition of a new class that would be extending JPanel and would have a
super.paintComponent call in it.

I found that I can get a graphics object by doing panelName.getGraphics()
and then I can use that to draw an image using the drawImage method. It
all works (almost), but the image 'flickers' and dissapears rather than
staying on the panel. How can I get this to happen, i.e. keep the image on
the panel?

Regards,
George
 
J

John B. Matthews

George said:
I want to draw an image on a JPanel, but without going through the
addition of a new class that would be extending JPanel and would have a
super.paintComponent call in it.

This seems odd. Can you explain further?
I found that I can get a graphics object by doing panelName.getGraphics()
and then I can use that to draw an image using the drawImage method. It
all works (almost), but the image 'flickers' and dissapears rather than
staying on the panel. How can I get this to happen, i.e. keep the image on
the panel?

Concerning paintComponent(): "f you do not invoke super's
implementation you must honor the opaque property, that is if this
component is opaque, you must completely fill in the background in a
non-opaque color. If you do not honor the opaque property you will
likely see visual artifacts." [1]

Perhaps a short example showing the problem would help. [2]

[1]<http://java.sun.com/javase/6/docs/api/javax/swing/JComponent.html>
[2]<http://pscode.org/sscce.html>
 
D

Daniel Pitts

George said:
Dear All,

I want to draw an image on a JPanel, but without going through the
addition of a new class that would be extending JPanel and would have a
super.paintComponent call in it.

I found that I can get a graphics object by doing
panelName.getGraphics() and then I can use that to draw an image using
the drawImage method. It all works (almost), but the image 'flickers'
and dissapears rather than staying on the panel. How can I get this to
happen, i.e. keep the image on the panel?

Regards,
George
Try this instead:

myPanel.add(new JLabel(new ImageIcon(pathToImage)));
 
K

Knute Johnson

John said:
George said:
I want to draw an image on a JPanel, but without going through the
addition of a new class that would be extending JPanel and would have a
super.paintComponent call in it.

This seems odd. Can you explain further?
I found that I can get a graphics object by doing panelName.getGraphics()
and then I can use that to draw an image using the drawImage method. It
all works (almost), but the image 'flickers' and dissapears rather than
staying on the panel. How can I get this to happen, i.e. keep the image on
the panel?

Concerning paintComponent(): "f you do not invoke super's
implementation you must honor the opaque property, that is if this
component is opaque, you must completely fill in the background in a
non-opaque color. If you do not honor the opaque property you will
likely see visual artifacts." [1]

Perhaps a short example showing the problem would help. [2]

[1]<http://java.sun.com/javase/6/docs/api/javax/swing/JComponent.html>
[2]<http://pscode.org/sscce.html>


John:

I think there is something wrong with the docs there. Why would you
paint a non-opaque color onto an opaque background if the component is
opaque? I've never had to use super.paintComponent() unless I wanted
whatever was drawn by the parent. Do you know how to create these
artifacts? Trying the code below, with any combination of opaque and
super, I see no problems. Of course, I could be missing the point
completely :).

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test extends JComponent {
public test() {
setOpaque(true);
}

public void paintComponent(Graphics g) {
// super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(10,10,10,10);
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
final JFrame f = new JFrame();
f.getContentPane().setBackground(Color.YELLOW);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
f.dispose();
}
});
f.add(new test(),BorderLayout.CENTER);
f.setSize(240,180);
f.setVisible(true);
}
});
}
}
 
J

John B. Matthews

Knute Johnson said:
John said:
[...]
I think there is something wrong with the docs there.

Well, they _did_ misspell invoke[r]. :)
Why would you paint a non-opaque color onto an opaque background if
the component is opaque?

In this context, I thought opaque meant "the component paints every
pixel within its bounds." But now I wonder.
I've never had to use super.paintComponent() unless I wanted whatever
was drawn by the parent. Do you know how to create these artifacts?

I _used_ to see it happening when I'd set opaque to true but fail to
paint every pixel. In retrospect, I was probably painting with a
partially transparent color.
Trying the code below, with any combination of opaque and super, I
see no problems. Of course, I could be missing the point completely
:).

On my implementation, the example's background is gray with no yellow at
all, I think due to multiple-buffering. Graphics#clearRect() says,
"Beginning with Java 1.1, the background color of offscreen images may
be system dependent. Applications should use setColor followed by
fillRect to ensure that an offscreen image is cleared to a specific
color."

With or without super.paintComponent(g), I get interesting artifacts
with non-opaque colors as I resize this window:

<code>
import java.awt.*;
import javax.swing.*;

public class OpaqueTest extends JComponent {

public OpaqueTest() {
this.setBackground(Color.yellow); // no effect
}

@Override
public void paintComponent(Graphics g) {
// super.paintComponent(g);
g.setColor(new Color(255, 0, 0, 128));
int w = getWidth();
int h = getHeight();
g.fillRect(0, 0, w, h);
g.setColor(new Color(0, 0, 255, 128));
g.fillRect(w/2 - w/4, h/2 - h/4, w/2, h/2);
}

@Override
public boolean isOpaque() {
return true;
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

public void run() {
create();
}

private void create() {
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(0, 2));
for (int i = 0; i < 4; i++) {
f.add(new OpaqueTest());
}
f.setSize(240, 180);
f.setVisible(true);
}
});
}
}
</code>

[...]
 
K

Knute Johnson

John said:
Knute Johnson said:
John said:
[...]
I think there is something wrong with the docs there.

Well, they _did_ misspell invoke[r]. :)
Why would you paint a non-opaque color onto an opaque background if
the component is opaque?

In this context, I thought opaque meant "the component paints every
pixel within its bounds." But now I wonder.
I've never had to use super.paintComponent() unless I wanted whatever
was drawn by the parent. Do you know how to create these artifacts?

I _used_ to see it happening when I'd set opaque to true but fail to
paint every pixel. In retrospect, I was probably painting with a
partially transparent color.
Trying the code below, with any combination of opaque and super, I
see no problems. Of course, I could be missing the point completely
:).

On my implementation, the example's background is gray with no yellow at
all, I think due to multiple-buffering. Graphics#clearRect() says,
"Beginning with Java 1.1, the background color of offscreen images may
be system dependent. Applications should use setColor followed by
fillRect to ensure that an offscreen image is cleared to a specific
color."

With or without super.paintComponent(g), I get interesting artifacts
with non-opaque colors as I resize this window:

<code>
import java.awt.*;
import javax.swing.*;

public class OpaqueTest extends JComponent {

public OpaqueTest() {
this.setBackground(Color.yellow); // no effect
}

@Override
public void paintComponent(Graphics g) {
// super.paintComponent(g);
g.setColor(new Color(255, 0, 0, 128));
int w = getWidth();
int h = getHeight();
g.fillRect(0, 0, w, h);
g.setColor(new Color(0, 0, 255, 128));
g.fillRect(w/2 - w/4, h/2 - h/4, w/2, h/2);
}

@Override
public boolean isOpaque() {
return true;
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

public void run() {
create();
}

private void create() {
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(0, 2));
for (int i = 0; i < 4; i++) {
f.add(new OpaqueTest());
}
f.setSize(240, 180);
f.setVisible(true);
}
});
}
}
</code>

[...]

If you change it to a JPanel instead of the JComponent, the yellow
background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real difference
between a JComponent and a JPanel.

In any of the cases however, I do not see any artifacts. I'm running
1.6.0_14-ea on Windows XP.
 
J

John B. Matthews

[...]
If you change it to a JPanel instead of the JComponent, the yellow
background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real difference
between a JComponent and a JPanel.

I get the same result.
In any of the cases however, I do not see any artifacts. I'm running
1.6.0_14-ea on Windows XP.

Thanks for looking at this. Interestingly, I get variations on [1] as I
resize the window under Java 1.5, but not 1.6 (Mac OS X 10.5.6).

[1]<http://tinypic.com/r/md32q0/5>
 
K

Knute Johnson

John said:
[...]
If you change it to a JPanel instead of the JComponent, the yellow
background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real difference
between a JComponent and a JPanel.

I get the same result.
In any of the cases however, I do not see any artifacts. I'm running
1.6.0_14-ea on Windows XP.

Thanks for looking at this. Interestingly, I get variations on [1] as I
resize the window under Java 1.5, but not 1.6 (Mac OS X 10.5.6).

[1]<http://tinypic.com/r/md32q0/5>

I see those artifacts on the link. I'll have to try this on Linux and
see what happens.
 
K

Knute Johnson

Knute said:
John said:
[...]
If you change it to a JPanel instead of the JComponent, the yellow
background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real difference
between a JComponent and a JPanel.

I get the same result.
In any of the cases however, I do not see any artifacts. I'm running
1.6.0_14-ea on Windows XP.

Thanks for looking at this. Interestingly, I get variations on [1] as
I resize the window under Java 1.5, but not 1.6 (Mac OS X 10.5.6).

[1]<http://tinypic.com/r/md32q0/5>

I see those artifacts on the link. I'll have to try this on Linux and
see what happens.

Results are the same on Linux as they are on Windows. Xubuntu 9.04 with
Sun JDK 1.6.0_13.

knute...
 
J

John B. Matthews

Knute Johnson said:
Knute said:
John said:
[...]
If you change it to a JPanel instead of the JComponent, the
yellow background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real
difference between a JComponent and a JPanel.

I get the same result.

In any of the cases however, I do not see any artifacts. I'm
running 1.6.0_14-ea on Windows XP.

Thanks for looking at this. Interestingly, I get variations on [1]
as I resize the window under Java 1.5, but not 1.6 (Mac OS X
10.5.6).

[1]<http://tinypic.com/r/md32q0/5>

I see those artifacts on the link. I'll have to try this on Linux
and see what happens.

Results are the same on Linux as they are on Windows. Xubuntu 9.04
with Sun JDK 1.6.0_13.

Yes, I got expected results on Fedora Core 10 & Java 1.6.0_07 with a
similar program that does not respect the opaque property [1]. In
contrast I get normal operation of several platforms for a program that
does respect the opaque property [2].

Perhaps it would be fair to say that the API admonition still applies,
even though it may not affect all implementations & versions equally.

[1]<http://sites.google.com/site/drjohnbmatthews/composite>
[2]<http://sites.google.com/site/drjohnbmatthews/kineticmodel>
 
K

Knute Johnson

John said:
Knute Johnson said:
Knute said:
John B. Matthews wrote:
[...]
If you change it to a JPanel instead of the JComponent, the
yellow background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real
difference between a JComponent and a JPanel.
I get the same result.

In any of the cases however, I do not see any artifacts. I'm
running 1.6.0_14-ea on Windows XP.
Thanks for looking at this. Interestingly, I get variations on [1]
as I resize the window under Java 1.5, but not 1.6 (Mac OS X
10.5.6).

[1]<http://tinypic.com/r/md32q0/5>
I see those artifacts on the link. I'll have to try this on Linux
and see what happens.
Results are the same on Linux as they are on Windows. Xubuntu 9.04
with Sun JDK 1.6.0_13.

Yes, I got expected results on Fedora Core 10 & Java 1.6.0_07 with a
similar program that does not respect the opaque property [1]. In
contrast I get normal operation of several platforms for a program that
does respect the opaque property [2].

Perhaps it would be fair to say that the API admonition still applies,
even though it may not affect all implementations & versions equally.

I think so or something strange 'could' happen. I just don't understand
how writing non-opaque color to the background solves the problem.
Wouldn't writing an opaque color do the same thing?
 
J

John B. Matthews

Knute Johnson said:
John said:
Knute Johnson said:
Knute Johnson wrote:
John B. Matthews wrote:
[...]
If you change it to a JPanel instead of the JComponent, the
yellow background will be drawn if it is opaque and you call
super.paintComponent(). That is apparently the one real
difference between a JComponent and a JPanel.
I get the same result.

In any of the cases however, I do not see any artifacts. I'm
running 1.6.0_14-ea on Windows XP.
Thanks for looking at this. Interestingly, I get variations on [1]
as I resize the window under Java 1.5, but not 1.6 (Mac OS X
10.5.6).

[1]<http://tinypic.com/r/md32q0/5>
I see those artifacts on the link. I'll have to try this on Linux
and see what happens.
Results are the same on Linux as they are on Windows. Xubuntu 9.04
with Sun JDK 1.6.0_13.

Yes, I got expected results on Fedora Core 10 & Java 1.6.0_07 with a
similar program that does not respect the opaque property [1]. In
contrast I get normal operation of several platforms for a program that
does respect the opaque property [2].

Perhaps it would be fair to say that the API admonition still applies,
even though it may not affect all implementations & versions equally.

I think so or something strange 'could' happen. I just don't understand
how writing non-opaque color to the background solves the problem.
Wouldn't writing an opaque color do the same thing?

D'oh, you're right! I've misread the sentence repeatedly. It should
probably say, "Further, if you do not invoke super's implementation you
must honor the opaque property, that is if this component is opaque, you
must completely fill in the background in an opaque color."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top