Two things you can do here:
- Read Painting in AWT and Swing
- Use a debugger and set a breakpoint in the paintComponent method. Then go up the freeze frame and see how you provide the Graphics parameter.
Just for information, here is the stack I got from the sample code that I posted at the end:
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 15 in TestPaint)) TestPaint.paintComponent(Graphics) line: 15 TestPaint(JComponent).paint(Graphics) line: 1054 JPanel(JComponent).paintChildren(Graphics) line: 887 JPanel(JComponent).paint(Graphics) line: 1063 JLayeredPane(JComponent).paintChildren(Graphics) line: 887 JLayeredPane(JComponent).paint(Graphics) line: 1063 JLayeredPane.paint(Graphics) line: 585 JRootPane(JComponent).paintChildren(Graphics) line: 887 JRootPane(JComponent).paintToOffscreen(Graphics, int, int, int, int, int, int) line: 5228 RepaintManager$PaintManager.paintDoubleBuffered(JComponent, Image, Graphics, int, int, int, int) line: 1482 RepaintManager$PaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1413 RepaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1206 JRootPane(JComponent).paint(Graphics) line: 1040 GraphicsCallback$PaintCallback.run(Component, Graphics) line: 39 GraphicsCallback$PaintCallback(SunGraphicsCallback).runOneComponent(Component, Rectangle, Graphics, Shape, int) line: 78 GraphicsCallback$PaintCallback(SunGraphicsCallback).runComponents(Component[], Graphics, int) line: 115 JFrame(Container).paint(Graphics) line: 1967 JFrame(Window).paint(Graphics) line: 3867 RepaintManager.paintDirtyRegions(Map<Component,Rectangle>) line: 781 RepaintManager.paintDirtyRegions() line: 728 RepaintManager.prePaintDirtyRegions() line: 677 RepaintManager.access$700(RepaintManager) line: 59 RepaintManager$ProcessingRunnable.run() line: 1621 InvocationEvent.dispatch() line: 251 EventQueue.dispatchEventImpl(AWTEvent, Object) line: 705 EventQueue.access$000(EventQueue, AWTEvent, Object) line: 101 EventQueue$3.run() line: 666 EventQueue$3.run() line: 664 AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method] ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 76 EventQueue.dispatchEvent(AWTEvent) line: 675 EventDispatchThread.pumpOneEventForFilters(int) line: 211 EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 128 EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 117 EventDispatchThread.pumpEvents(int, Conditional) line: 113 EventDispatchThread.pumpEvents(Conditional) line: 105 EventDispatchThread.run() line: 90
The Graphics parameter is displayed here:
RepaintManager.paintDirtyRegions(Map) line: 781
The entered fragment is presented below:
Graphics g = JComponent.safelyGetGraphics( dirtyComponent, dirtyComponent);
If you look at it, you will see that it extracts graphics from the JComponent itself (indirectly using javax.swing.JComponent.safelyGetGraphics(Component, Component) ), which itself takes it ultimately from its first “heavy parent” (bound to the boundaries of the component), which he himself takes it from the corresponding resource.
Regarding the fact that you need to drop Graphics on Graphics2D , it just happens that when working with the Window Toolkit Graphics actually expands Graphics2D , but you can use other Graphics that are “not required” to extend Graphics2D (this does not happen very often, but AWT / Swing lets do it).
import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; class TestPaint extends JPanel { public TestPaint() { setBackground(Color.WHITE); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawOval(0, 0, getWidth(), getHeight()); } public static void main(String[] args) { JFrame jFrame = new JFrame(); jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame.setSize(300, 300); jFrame.add(new TestPaint()); jFrame.setVisible(true); } }