paintComponent on JPanel, image flashes and then disappears - java

I have a JApplet (MainClass extends JApplet), a JPanel (ChartWindow extends JPanel) and a Grafico class.
The problem is that the Grafico class instance has 2 JPanel that should show 2 images (1 for each panel) but the images are shown and after a little while they disappears: instead of them i get a gray background (like an empty JPanel). This happens for every repaint() call (that are made in the ChartWindow class)
the MainClass init() contains
chartwindow=new ChartWindow();
add(chartwindow)
chartwindow has a Grafico instance.
it's the ChartWindow's paintComponent (override)
paintComponent(Graphics g)
{
super.paintComponent(g);
Image immagineGrafico=createImage(grafico.pannelloGrafico.getWidth()
,grafico.pannelloGrafico.getHeight());
Image immagineVolumi=createImage(grafico.pannelloVolumi.getWidth()
,grafico.pannelloVolumi.getHeight());
Graphics2D imgGrafico=(Graphics2D)immagineGrafico.getGraphics();
Graphics2D imgVolumi=(Graphics2D)immagineVolumi.getGraphics();
grafico.draw(imgGrafico,imgVolumi,mouseX,mouseY);
((Graphics2D)grafico.pannelloGrafico.getGraphics()).drawImage(immagineGrafico,0,0,this);
((Graphics2D)grafico.pannelloVolumi.getGraphics()).drawImage(immagineVolumi,0,0,this);
}
grafico's JPanels are added this way in the ChartWindow's constructor
grafico=new Grafico()
................
add(grafico.pannelloGrafico);
add(grafico.pannelloVolumi);
Tell me if you need more information, thank you very much :-)

You need to override the JPanel's paintComponent rather than the chart window's if you want to paint on them. What happens is that everytime the JPanel paints itself the default paint would overwrite your images.
class PanelloVolumi extends JPanel{
//some code
public void paintComponent(Graphics g){
//paint one image here
}
}
And do the same for the other JPanel.
Then add instances of these JPanels to your Applet.

Related

Adding a BufferedImage to a JPanel on JLayerPane

So, I have a JLayeredPane (technically a class subclassing JLayeredPane actually). On that is a JPanel. I want to add a BufferedImage to the Jpanel.
public class BigMap extends JLayeredPane implements MouseListener
JPanel mapPanel;
BufferedImage theMap;
public BigMap (BufferedImage m){
theMap = m;
mapPanel = new JPanel();
add(mapPanel, 0);
mapPanel.setBounds(0, 0, 640, 640);
//other unimportant stuff
}
#Overrride
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D gmap = (Graphics2D) mapPanel.getGraphics();
gmap.drawImage(theMap, null, 0, 0);
//some other stuff which is working just fine
}
The issue is that the BufferedImage isn't displaying. The JPanel is definately present as I can set its backgroundColour and see it if I wish. I realise that JLayeredPane doesn't have a layout manager and have had to set the bounds for the JPanel but that shouldn't be an issue for the JPanel itself, surely? And given that BufferedImage lacks methods to control its size directly I don't see how I'd overcome that if it were.
Any help appreciated.
The problem here is that you override the paintComponent() method of your layered pane, not the JPanel. The JPanel will paint itself later, as one of the children of your layered pane, and this will wipe out what you painted.
In general, a paintComponent() method should paint into the Graphics that was given to it, not into some other component's graphics.

Java swing draw objects over other components

I am trying to make a small paint program. I am drawing objects over a JPanel which is on top of JFrame (I am using Netbeans 6.9). I have some basic functionality like font, line and fillRectangle. I am using the standard method to draw which is to override paintComponent().
class .... extends JPanel
{
#Override
void paintComponents(Graphics g)
{
.......
}
}
The problem is that when I draw a text,line over a region then it is drawn behind it rather than on top of it. Basically I want to draw objects on top of all other objects that have previously been drawn on the JPanel. I really do not want to switch to other types of layered pane. One very naive method will be to undo every object and paint them in reverse order (last one first).
You will need to override paintComponent(Graphics g) and do not forget to call super.paintComponent(Graphics g);
class .... extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);//honor paintComponent an call super to draw other components that were added to the JPanel
.......
}
}
You may also need to override getPreferredSize(..) of JPanel and return an appropriate size so the JPanel will be visible:
class .... extends JPanel
{
#Override
public Dimension getPreferredSize()
{
return new Dimension(300,300);
}
}
EDIT:
Depending on what you are doing you may also want to have a look at the GlassPane which will allow you to set a transparent pane over the entire JFrame window and can be painted too, which will cause the graphics to be drawn above all others like so:
This is an old question, but I had the same problem and solved it by overriding paintChildren(Graphics g) instead of paintComponent.
As the Oracle documentation states, the order of execution for the three paint methods is:
protected void paintComponent(Graphics g)
protected void paintBorder(Graphics g)
protected void paintChildren(Graphics g)
So, paintChildren(g) is run last, which means whatever we draw inside it is drawn on top of all previously drawn components.

Java PaintComponent size and position in a subclass of an abstract class that extends Jpanel

I'm building a simple chess game and am stuck on trying to paint drawings on a Panel
I have a board ready and on the board there are panels. those panels are 70x70px and next thing i want to do is use THAT ENTIRE SURFACE to draw chess pieces.
i made an abstract class Pieces that extends JPanel.
public abstract class Piece extends JPanel
One of the pieces is ofcourse, a Pawn :
public class Pawn extends Piece
in the Pawn class I have paint component :
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(Color.GREEN);
g.fillOval(0, 0, w, h);
System.out.println("height:"+h+" width:"+w);
}
This does not seem to work. the output prints height = 10px and width = 10px; .... but it is suposed to be 70px and 70px. I also see the green oval painted inside a 10x10 square, which is inside my Panel...
I tried a setSize(70,70) which does not realy do the trick...
I also tried SetPreferredSize but well It did not really work out either.
I really want to keep my abstract class and subclasses...
### EDIT ###
I've used setPreferredSize again and I can now actually draw my green circle on the Jpanel. but an error remains as in it is not the whole surface of the Jpanel Used... there remains a gap at the top , a screenshot:
if you only to set Background to Color.GREEN then extends JComponent,
if you want to add only Image then look for Icon in JLabel, note JLabel is transparent, non-opaque by default,
any JComponent can returns setXxxSize,
not all LayoutManagers accepted setXxxSize,
example JComponent with setXxxSize

Java - JPanel won't show up on JFrame when overriding JFrame's paint

I have a JFrame on which I am using overriding the paint method to display some graphics. I also want to add a JPanel to it that will show up on top of the graphics. Right now, all I see is the graphics created from JFrame paint method.
Here's my JPanel:
public class NoteDraw extends JPanel {
public NoteDraw() {
setSize(200, 100);
setBackground(Color.BLACK);
}
#Override public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 100, 100);
}
}
Here's my JFrame:
public class ui extends JFrame {
public void paint(Graphics g) {
//do some drawing here...
}
}
Here's my main:
public class Main {
static ui main_gui = new ui();
public static void main(String[] args) {
NoteDraw note = new NoteDraw();
main_gui.getContentPane().add(note);
main_gui.setVisible(true);
}
}
You should NEVER override the paint() method of a JFrame (unless you really know what you are doing). This method is responsible for all the optimized painting behaviour of Swing.
Custom painting should always be done by overriding the paintComponent() method of a Swing component like you have done on your NoteDraw panel.
The reason the code in the paint method doesn't show is because the NoteDraw panel is opaque and therefore the panel paints over top of the Graphics code in your paint method.
So the solution is to move the Graphics painting code to the NoteDraw panel.
Or if you are trying to create some kind of background image for your frame then you can try using the Background Panel.
Or if you truly do need custom painting then you create a background panel and override the paintComponent() method. Then you set the layout to a BorderLayout and add this panel to the frame. Then you make your NoteDraw panel non-opaque and add it to the custom background panel. Now the background will show through on the NoteDraw panel.
Remember to call super.paint() when you override your paint() method.
This way, you still use the behavior defined in the parent class, and you can add your modifications safely.
Resources :
sun.com - Using the Keyword super

Java Swing NullPointerException when drawing

I'm using a custom JLayeredPane.
I have several Shapes which needed to be drawn on different layers in the JLayeredPane.
To test this I create a JPanel and ask its graphics. Then I draw a test rectangle on that JPanel (preparing the graphics) and in my paintComponent method from the JLayeredPane I finally draw everything. But this fails (NullPointerException).
public class MyCustomPanel extends JLayeredPane {
// test
JPanel testpane;
Graphics g2;
// test
// constructor
public MyCustomPanel() {
testpane = new JPanel();
this.add(testpane, new Integer(14));
g2 = testpane.getGraphics();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2.drawRect(10, 10, 300, 300);
}
}
// run:
//Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
// at view.MyCustomPanel.paintComponent(MyCustomPanel.java:65)
Why can't I draw on such a JPanel from within my JLayeredPane? I can draw directly on my JLayeredPane from within my paintComponent method but that's on the default Panel from the JLayeredPane. I need to create and draw on several layers which are added in my JLayeredPane.
What am I doing wrong? :s
You should use g2 casting the Graphics that is passed to you:
Graphics2D g2 = (Graphics2D)g;
Why don't you try decoupling things?
class InnerPanel extends JPanel
{
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.drawRect(....);
}
}
class MyLayered extends JLayeredPane()
{
MyLayered()
{
this.add(new InnerPanel(), 14);
}
}
this makes more sense..
Also because you are trying to do something that doesn't agree with Swing behaviour.
Swing will care by itself to call the appropriate paint methods over things that must be displayed, and to go with this protocol you should tell Graphics objects what to draw when Swing asks it to your objects (calling the paint) method, not when you want to do it.
In this way whenever Swing wants to draw your JLayeredPane you just draw things on a Graphic object of other things without considering that Swing will call their appropriate methods when it's the right time to do so.
In conclusion: you can't draw something on a Graphic object when you want it. You can do it just inside methods invoked by Swing, because otherwise Graphics of these objects doesn't mean anything
The variable g2 is probably null because you set it in the constructor, not when drawing. Instead, use the "g" that was passed in.
You can only get a legitimate Graphics from a component that is currently being painted. Otherwise, it's not valid. At the point you're requesting it, the MyCustomPanel() isn't being displayed, and neither is testpane.

Categories