0

I have trouble understanding a fundamental concept in Java 2D.
To give a specific example:
One can customize a swing component via implementing it's own version of the method paintComponent(Graphics g)
Graphics is available to the body of the method.
Question:
What is exactly this Graphics object, I mean how it is related to the object that has the method paintComponent? Ok, I understand that you can do something like:

g.setColor(Color.GRAY);
g.fillOval(0, 0, getWidth(), getHeight());

To get a gray oval painted. What I can not understand is how is the Graphics object related to the component and the canvas. How is this drawing actually done?
Another example:

public class MyComponent extends JComponent {

     protected void paintComponent(Graphics g) {

                System.out.println("Width:"+getWidth()+", Height:"+getHeight());

            }

    public static void main(String args[]) {

                JFrame f = new JFrame("Some frame");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setSize(200, 90);
                MyComponent  component = new MyComponent  ();
                f.add(component);
                f.setVisible(true);       
          }
 }

This prints

Width:184, Height:52

What does this size mean? I have not added anything to the frame of size(200,90).

UPDATE:
I understand that I must override paint to give in the Graphics g object the hints required to do the repaint and that I do not have to create a Graphics object as one will be given by platform.
What happens after that is what I can not understand.
E.g. does Graphics represent the screen and the object is painted accordingly on screen as soon as I start calling the various g.setXXX methods?
Does it get stored in a queue and there is a 1-1 association among g and each component? So the framework uses each g of each component to paint it one at a time?
How does this work? Any help on this is highly welcome

Thanks

4

4 回答 4

2

I understand your problem as I struggled with it for some time when I was learning Java graphics. It's not just Java 2D graphics - it is part of AWT.

When you create a JFrame or some other top-level object, it does a lot of work "behind the scenes" - part of which is creating a Graphics object. (There is not explicit notification of this, though if you stepped through the code with a debugger you may see classes which create the Graphics).

You then create components which you add, or register with, the top-level object. These all have to implement a call-back method, including

paint(Graphics g);

You will then @Override these methods so that when the component is rendered it uses YOUR paint method.

Do not try to save the Graphic or create a new one. Think of it as the framework taking the responsibility off you.

The size of components is often taken out of your hands. If you use a layout manager then it may decide to resize your component.

If you are coming from a procedural imperative background you may well have problems (I came from FORTRAN). My advice would be to try a number of tutorials and - at some stage - enlightenment will start to come.

The general documentation for Java graphics is poor. There are many concepts which are opaque (see How does Java Graphics.drawImage() work and what is the role of ImageObserver ). The early implementation was rushed through and had many bugs. Even now it is often unclear whether and in what order you should call methods such as setPack() and setVisible().

This doesn't mean you shouldn't use it! Just that the learning curve is a bit longer than IMO it should be.

MORE: Also YOU don't decide when something is painted, the framework does. paint(g) really means "The framweork is repainting its components. What to you want this component to provide at this stage".

Maybe providePaintingInstructionsWhenRequiredForComponentGraphics(Graphics g) would be a useful name.

Similarly repaint() does not repaint at your orders, but when the system thinks it should. I haven't found it useful.

If you (say) resize a component interactively every slight change will normally trigger a paint(g). try putting a LOG.debug() in the paint code and seeing when it gets called.

于 2011-01-02T10:45:49.337 回答
2

这个尺寸是什么意思?我没有在尺寸(200,90)的框架中添加任何东西。

您将组件添加到框架并将框架的大小设置为 (200, 90)。框架内容窗格的默认布局管理器是 BorderLayout,这意味着您添加的组件将获得所有可用空间。框架需要一些空间用于标题栏和边框,因此您的组件可以获得剩余空间。

于 2011-01-02T16:51:05.030 回答
1

想像Graphics一张纸,你可以在上面画出那一刻Component的样子。绘制完成后,框架工具包将修剪边缘并显示您绘制的内容以显示组件。此外,下次绘制组件时,您将在另一张纸上绘制,所以不要保留旧的。Graphics

于 2011-01-02T12:04:50.887 回答
1

该组件不创建静态图形对象关联。

图形对象是平台句柄的包装器,可以访问物理设备,如屏幕。它仅在“绘制”执行时有效,您不能存储它并在以后重复使用它。它是由“工具包”管理的资源。

组件本身是窗口系统之上的抽象,它很快与该设备关联以进行渲染。

编辑

如果您觉得需要从“paint”回调中绘制出来,您可以强制调用“getGraphics”这样的关联。这应该是一种非常罕见的情况,您总是应该在之后处理图形。

于 2011-01-02T11:52:52.063 回答