inside a paintcomponent. it takes g as parameter, and g can be graphics or graphics2d. the class extends jpanel. then:
super.paintComponent(g);
this.setBackground( Color.BLACK );
if g is graphics it works, but if it's graphics2d it doesn't. it compiles with both, but graphics2d doesn't change the background color. how come?
JPanel (which is a subclass of JComponent) only has a paintComponent(Graphics) method. It does not have a method with the signature paintComponent(Graphics2D).
Overriding the paintComponent(Graphics) method can be accomplished by the following:
public void paintComponent(Graphics g)
{
// Do things.
}
However, defining a method with the signature with paintComponent(Graphics2D) like the following is legal, but it won't ever be called, as it is not overriding any method that is defined in JComponent:
public void paintComponent(Graphics2D g)
{
// Do things.
// However, this method will never be called, as it is not overriding any
// method of JComponent, but is a method of the class this is defined in.
}
The Java API specifications for the JComponent class (which is the superclass of JPanel) has a method summary which lists all the methods that are part of the class.
More information about painting in Swing;
Lesson: Performing Custom Painting from The Java Tutorials
Painting in AWT and Swing
Related
I am reading swing tutorial. From what is mentioned there:
The paintComponent method of JComponent is automatically called
when a frame is drawn/re-drawn.
But, what I do not understand is what is the Graphics Object that is passed to it. I do not see
any new object of Graphics type being instanstiated and passed. so how does all this happen?
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g;
g2.drawimage(image,x,y,null);
//
}
I guess it is a similar situation with actionlisteners. But in this case, The actionPerformed is called automatically when event occurs such as button click and the events gets passed to the actionPerformed. There is no need to separately call this method and pass the Actionevent object. But I do not understand how it happens with paintComponent method.
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event){
//do something
}
});
Thanks
The Graphics object is created by the paint sub system.
You should never be calling paintComponent yourself and should simply allow the paint system deal with it. Even if you wanted to capture or print the component using your Graphics context (from something like BufferedImage), you should be using print or printAll
Take a look at Painting in AWT and Swing
They are similar issues. The Graphics object is created by the Swing library at the request o the JVM and passed into the paintComponent(Graphics g) method when the JVM makes this method call. Because you yourself are not directly calling this method, you never see the object being created.
I have a canvas and I want to draw a rectangle based on a JButton click.
So in other words
private void jb_drawActionPerformed(ActionEvent evt) {
// draw a rectangle method
}
Basically, how do I encorporate the pain(Graphics g) thingamagic in that method? or should I make the rectangle an object and call a "render" method from that object? If so, can someone link a tut?
private void jb_drawActionPerformed(ActionEvent evt) {
myrectange.render(x,y); // ????
}
General Comments and Recommendations
One way: Draw in a BufferedImage getting your Graphics object from the BufferedImage, and then draw the BufferedImage in the JComponent's (JPanel's?) paintComponent method.
If you do it this way, you will use the Graphics object directly obtained from the BufferedImage to do your drawing.
Don't forget to dispose of this Graphics object when done with it.
The actual drawing though is done in the JPanel's paintComponent(...) method (see below).
Another way: change a class field, and have the JPanel's paintComponent method use that field when painting. For instance, if you want to paint multiple Rectangles, create an ArrayList<Rectangle> add to it in your ActionListener, call repaint() and have the paintComponent(...) method iterate through the List, drawing rectangles held by it.
Note that the paintComponent(...) method is never called directly but rather you suggest to the JVM that it call it by calling repaint().
Never dispose of a Graphics object that was given to you by the JVM, for instance the one passed into the paintComponent(Graphics g) parameter.
Links
Basic Tutorial: Lesson: Performing Custom Painting
More advanced concepts: Painting in AWT and Swing
I want to draw a straight line in JFrame using Line2D.Double, also I want do it with constructor (not through method). How I must declare variable g like in example on docs.oracle.com?
public void paint (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
...
}
Painting is always done in a method. In particular custom painting in Swing is done in the paintComponent() method of a Swing component like JComponent or JPanel.
Read the Swing tutorial on Custom Painting for a better explanation and examples.
1) I want to draw a straight line in JFrame using Line2D.Double, that not possible you have to put there JLabel, JPanel or plain JComponent, example here
2) if you want to paint directly to the JFrame, then you have to (use method paint()) to the GlassPane or RootPane
3) for Swing is there method painComponent(as mentioned both posters), not paint
The drawing/painting occurs event driven. That is when a part of the JFrame has to be (re-)drawn paint and paintComponent will be called.
You can merely add a component to the content pane of the JFrame in the constructor. That would then draw the line by overriding paintComponent.
You could create a JPanel, which has a:
List<Shape> shapes;
shapes.add(new Line2D.Double(...));
and then in paintComponent draw all shapes. But that is overdone.
You mean how to get a Graphics2D object from with a constructor? That is not the way to do it, Graphics2D is an interface and the implementation classes are not in the API. However, you can get a graphics object from any component with
(Graphics2D)component.getGraphics()
I'm creating a game and I want some of the image to be repainted while others to stay constant. I had put my methods in the paint() on java applet but this seems to access the methods in an endless loop.
How do I create a "driver method" that will access my methods but also use the draw() at the same time?
public void paint (Graphics g)
{
bufferGraphics.clearRect (0, 0, dim.width, dim.height);
//mainScreen ();
g.drawImage (offscreen, 0, 0, this);
} // end Paint method
public void update (Graphics g)
{
paint (g);
}
public void main (String[] args)
{
game ();
}
Overriding paint() and update() is done when using AWT. Since you are just learning about painting why not write a Swing applet and extend JApplet, since Swing is more commonly used these days? Then custom painting is done by extending JPanel or JComponent. Then you add this component to the content pane of the JApplet, just like it was a JFrame.
Read the section from the Swing tutorial on Custom Painting for more examples of painting with Swing.
i have a jrame on which i add some JComponent objects.
Each JComponent has a list of containers i add by using JComponent.add( Component).
Now in my main JComponent class, called MyComponent, i override the protected method paintComponent where i can paint things, which works pretty fine.
But i dont want to paint on the main JComponent, i only want to paint on the containers i have added to my main JComponent.
So in MyComponent in paintComponent i do the following.
protected void paintComponent( Graphics g) {
super.paintComponent( g);
Graphics page_g = this.getPage( "main").getGraphics();
page_g.setColor( Color.RED);
page_g.drawRect( 10, 10, this.getWidth() - 20, this.getHeight() - 20);
page_g.setColor( Color.BLUE);
page_g.drawString( "HELLO WORLD", this.getWidth() / 2, this.getHeight() / 2);
}
The line this.getPage( "main").getGraphics(); takes the Graphics object from one of my containers added to the MyComponents list of containers and of course to the main component list using JComponents add method. The container is set to visible by calling the setVisible( true); method.
But nothing happens. The screen is empty. When i replace page_g with g, then painting works, because its painting on my JComponent (MyComponent), but i want to paint on the container which is a children of MyComponent in this case.
I often heard "Never use getGraphics()". But how else can ONLY draw on sub components of a parent component when the parents paintComponent method gets called?
Really the best bet is to have the classes that are actually doing the custom painting override their own paintComponent() method. Let the AWT worry about the graphics contexts.