I came across this code. I thought I alleviate this confusion before I run into any hiccups along the way in programming. I am having trouble understanding whether the paint or the actionPerformed method gets executed first in Board class. I hope my java comments are correctly stated.
The thing is, I took introductory Java in the summer and graphics was only introduced towards the end of the course. The class used ImageIcon and we never touched the drawImage method and Image abstract class. I also do not understand the paint method at all. This code is more involved than the Java graphics lecture I had. Based on the Java API, the paint method originated from the JComponent class which is JPanel's superclass.
So what is this parameter Graphics g that the paint method takes in all about and how should I think about it? How does the paint method know which object of a graphics class to paint. I looked at the Java API and it says Graphics is an abstract class. How can g be an object if its data type is abstract? I am saying g is an object because the code is calling the drawImage method on the object g.
On a side note, does repaint method mean erase the content in the JPanel and redraw the entire component like rendering?
public class Board extends JPanel implements ActionListener{
private Image apple;
private int apple_x;
private int apple_y;
// over-riding the paint method from the JComponent Class
public void paint(Graphics g){
// recursively call the paint method
super.paint(g);
g.drawImage(apple, apple_x, apple_y, this);
}
// does this method gets called first or the top one?
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Drawing in Java (and basically all current windowing systems) follows the Hollywood principle:
You don't call me; I call you.
I.e. you can tell the system that a certain area will need to be redrawn (repaint()). But you'll have to wait until the system calls you to do the drawing. In Java, the system will call the paint() method and will pass you a Graphics instance to use for drawing.
So the order of event is:
actionPerformed()
paint()
Graphics is often called a graphics context. It's an object used for drawing. Depending on the system and the current requirements, the drawing might go directly on the screen or into an offscreen buffer that is later copied to the screen. The Graphics instance takes care of the details.
Someone can correct me if I am wrong.
Yes, graphics is an abstract class. But an instance of any class that inherits Graphics (such as Graphics2D) can be passed as graphics. If I recall correctly this is call upcasting. g is passed by the UI thread that called paint(), either because the object was invalidated, or has to be updated.
The graphics object is a reference to the actual bitmap that appears to the user.
Related
So I have a college project to make paint program using swing , I need to clear Graphics object and but from a method in an outside class and then draw all shapes again (refreshing the graphics object) as I'm passing the graphics object through this method .
the class is responsible for saving all shapes i draw on this graphics (in an ArrayList ) .
SO how can I do this if I can't call Super.paintComponent that exists in the Jpanel class .
as I'm passing the graphics object through this method .
You should NOT be passing the Graphics object. The paintComponent() method (or any method is invokes) should always use the Graphics object passed to the paintComponent() method.
SO how can I do this if I can't call Super.paintComponent that exists in the Jpanel class .
In the class where you do the custom painting you create a clear() method. This will simply remove all the Shape objects from the ArrayList and then invoke repaint().
See the DrawOnComponent example from Custom Painting Approaches that demonstrates how this is done.
Found a very simple answer which is "Draw white rectangle, then draw shapes again"
that would simply solve my problem :)
I'm new to making GUIs in Java. As I understand, there's a class called Graphics which is in charge of drawing shapes in a JPanel. When my application starts, I call the paintComponent method, which draws the board of the game I'm programming, and the paintComponent method takes a Graphics g as input. However, later on, I want to update the board, so how do I tell the same g that drew the board at the start of the game to draw something else when the user does something like clicking?
I believe this should have a very simple answer.
Every JComponent (Swing component) has a repaint() method, just call it to tell the DrawingManager to redraw your component.
All your drawing code should be in paintComponent method, that means that you don't draw anything anywhere else (you draw only in the flow of invocation of paintComponent, you can have drawing code structured in methods of course).
This method needs to have access to the state that indicates what and where should be drawn. It is because the OS could request repainting, and then only the painting methods from JComponent are called.
When you invoke repaint() on your JComponent, then in short time the paintComponent() method of the component on which you requested repainting will be called by the drawing thread, and you should draw only in this drawing thread.
Try repaint() or revalidate(), it should work.
I call the paintComponent method
No, you should never call the paintComponent() method directly. Swing will call the method for you when the component needs to be repainted.
I want to update the board
Then you need a "setter" method. Think of other Swing components. They have methods like "setForeground(), setBackground(), setText()" etc.
So if you want to change your component then you need to create appropriate setter method to change the properties of your class. Then in the method you save the property and simply invoke repaint() and Swing will repaint your component. So now your paintComponent() method needs to check the property you just set to do the appropriate painting.
public void setSomeProperty(Obect someProperty)
{
this.someProperty = someProperty;
repaint();
}
....
protected void paintComponent(Graphics g)
{
super.paintComponent();
// paint the board
if (someProperty != null)
// paint the property
}
So I'm trying to learn Java graphics and this bit of code has me perplexed. I don't understand a couple things here:
Why is paintComponenet used twice for the name of the method and as
we call a method from super (JPanel)?
What is Graphics g, isn't it just a reference variable for an object
of Graphics since we don't set it equal to = new Graphics();?
Why does the method name in my class have to be paintComponent to
call upon the method paintComponent from JPanel or super?
The method in my class paintComponent takes the parameter of a
Graphics object but when does paintComponent even get called and
when is the parameter of Graphics inserted?
Essentially I need someone to explain this code to me.
//note this is all in a class that extends JPanel, my JPanel is later placed in
//a JFrame which is run through main
public void paintComponent(Graphics g)
{
int width = getWidth();
int height = getHeight();
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(10, 10, 200, 200);
g.setColor(Color.BLUE);
g.drawRect(10, 10, 200, 200);
}
Why is paintComponenet used twice, for the name of the method and as we call a method from super (JPannel)
It's not "used" twice. It is overridden once, but you want to call the parent (JPanel) class's super method so that you're sure that it does its own house-keeping painting, including painting its children and clearing out any dirty bits from the screen.
What is Graphics g, isn't it just a reference variable for an object of Graphics since we don't set it equal to = new Graphics();
It's a Graphics parameter. You don't set it = new Graphics() because the JVM does this for you. It calls the method behind the scenes when needed, and provides the parameter.
Why does the method name in my class have to be paintComponent to call upon the method paintComponent from JPannel or super
It has to override the super's method so that the JVM calls the right method when it wants to draw the GUI.
The method in my class paintComponent takes the parameter of a Graphics object but when does paintComponent even get called and when is the parameter of Graphics inserted.
Again, it is called by the JVM when either your program wants to repaint the GUI, such as when you call repaint() or when the operating system wants to repaint a window such as if a window is minimized and restored.
You really really want to read the graphics tutorials:
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
1) Why is paintComponenet used twice, for the name of the method and as we call a method from super (JPannel)
Here the line super.paintComponent(...), means we want the JPanel to be drawn the usual Java way first (this usually depends on the opaque property of the said JComponent, if it's true, then it becomes the responsibility on the part of the programmer to fill the content area with a fully opaque color. If it is false, then the programmer is free to leave it untouched. So in order to overcome the hassle assoicated with this contract, super.paintComponent(g) is used, since it adheres to the rules, and performs the same task, depending upon whether the opaque property is true or false).
2) What is Graphics g, isn't it just a reference variable for an
object of Graphics since we don't set it equal to = new Graphics();
and
4) The method in my class paintComponent takes the parameter of a
Graphics object but when does paintComponent even get called and when
is the parameter of Graphics inserted
paintComponent method is where all of your painting code should be placed. It is true that this method will be invoked when it is time to paint, but painting actually begins higher up the class heirarchy, with the paint method (defined by java.awt.Component.) This method will be executed by the painting subsystem whenever you component needs to be rendered. Its signature is:
public void paint(Graphics g)
javax.swing.JComponent extends this class and further factors the paint method into three separate methods, which are invoked in the following order:
protected void paintComponent(Graphics g)
protected void paintBorder(Graphics g)
protected void paintChildren(Graphics g)
The API does nothing to prevent your code from overriding paintBorder and paintChildren, but generally speaking, there is no reason for you to do so. For all practical purposes paintComponent will be the only method that you will ever need to override
Let's say we have the following situation:
JPanel panelp=new JPanel();
paintSomething(panelp.getGraphics();
and somewhere else in a different object, the method:
void paintSomething(Graphics g){ /*code*/ }
I don't want to override paintComponent method of panelp. How can I paint something to panelp from the method paintSomething using the Graphics of panelp?
whatever.getGraphics() is snapshot is the snapshot that will go away when
after first repaint
JComponets are repainted internally from Mouse or Key Events, these events are implemented in the concrete JComponets API
simple example for usage of whatever.getGraphics() is printing to the printer or saving current GUI as printscreen to the e.g. JPEG or PGN File
basic stuff is described in the 2D Graphics
You could draw your stuff in the paintSomething into a BufferedImage which you can then draw to the panel by overriding paintComponent
I'm Basically programming a simple game engine but I'm having problems with my sprites/images not appearing when they should... or at all!
I'll try and keep this as simple as possible. I have a Sprite, GameEngine and Display class. In the gameloop, I have a method that sets the new position of my Sprite (so it just sets the x and y variables). Next I call a transform method which does the following:
public void transform() {
affineTransform.setToIdentity();
affineTransform.translate(x, y);
}
Following that, I then call a draw method in the Sprite:
public void draw() {
graphics2D.drawImage(image, affineTransform, jFrame);
}
Finally, in my thread I then call repaint() on the JFrame (the Display class). My paint method for that class is as follows:
public void paint(Graphics g) {
g.drawImage(backbuffer, insets.left, insets.top, this);
}
But nothing is appearing, apart from a black screen!
I'm also getting confused between Graphics g, and Graphics2D and when to use either. (The overridden paint method uses Graphics g). For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
Another thing that is confusing me is this AffineTransform... I've read the documentation but I'm still utterly confused on how and when to use it - and what exactly it seems to do. Is there any explanation in relatively simple terms?
Surely this should be working... am I missing something out here?
To answer part of your question:
From the Graphics2D JavaDoc
This Graphics2D class extends the Graphics class to provide more sophisticated control over geometry, coordinate transformations, color management, and text layout. This is the fundamental class for rendering 2-dimensional shapes, text and images on the Java(tm) platform.
Essentially, with Graphics2D you can do much more than you can with Graphics. And with a Sun JVM 1.5+, it should be safe to cast the Graphics object you get in paint() to Graphics2D
I just noticed this: For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
You should make sure you're not drawing on a Graphics[2D] canvas (I'll use this term to refer to the drawable area that the Graphics[2D] object provides) that you later throw away. If you're drawing your image on a separate canvas, you should ensure that you then draw that image onto your actual display canvas.
I don't really have a good explanation of AffineTransform but maybe these will help?
http://www.javalobby.org/java/forums/t19387.html
https://secure.wikimedia.org/wikipedia/en/wiki/Affine_transformation
From Wikipedia - In general, an affine transformation is composed of linear transformations (rotation, scaling or shear) and a translation (or "shift"). Several linear transformations can be combined into a single one. Basically, you use this class to perform operations such as rotation, translation, zoom etc.