Java中的图形类(Graphics Class)是如何工作的?

3

最近,我一直在尝试使用Java图形进行一些工作。现在Graphics类是抽象的,这意味着它本身不能被实例化,但它的子类可能被实例化。那么在下面的代码中发生了什么(成功创建了一条线)。

import javax.swing.*;
import java.awt.*;

public class line extends JPanel {
    public void paintComponent(Graphics g) {
        g.drawLine(0, 0, 90, 90);
    }

    public static void main(String[] args) {
        JFrame jf = new JFrame();
        jf.add(new line());
        jf.setSize(500, 500);
        jf.setVisible(true);
    }
}

现在有几件事情我不太明白。首先,当调用line时,它必须执行line类中的paintComponent方法。这是静态方法的属性(使用类名调用)。但是paintComponent方法没有静态修饰符。

虽然这个程序可以工作,但我们必须假设paintComponent确实被调用,并期望一个Graphics对象作为参数。但是当它被调用时,它没有参数。为什么这不会创建错误?我进行了一些测试,将String和空值传递给一个期望Integer对象的方法。两个程序都出错了。

因此,某种方式创建了一个名为g的图形对象,并使用drawline方法。但是Graphics是抽象的。

好的,这里是我的问题:

  1. 为什么paintComponent在其类line被调用时自动调用,而paintComponent不是静态的?

  2. 为什么paintComponent接受空参数,而它期望一个Graphics对象?

  3. 由于Graphics是抽象的且无法实例化,因此如何制作Graphics对象g?

求助于Stack Overflow,你是我的唯一希望。

编辑:好的,我认为这个问题已经得到了很好的回答,谢谢!


你如何知道paintComponent()被调用时没有参数? - irrelephant
嗯,Graphics代表了一个_图形上下文_。我不太确定你还在谈论什么,因为很明显paintComponent不是一个静态方法...它是从JComponent.paintComponent中重写的。据我所知,它不接受空参数。传递进来的Graphics是由底层的AWT代码创建的。 - obataku
new line() 创建了 line 类的一个实例。因此,paintComponent 没有从静态引用中调用。 - MadProgrammer
2
花点时间阅读一下http://www.oracle.com/technetwork/java/painting-140037.html。它应该会帮助你理解一些你所拥有的问题...另外,确保你调用`super.paintComponent(g)` ;) - MadProgrammer
3个回答

8
  1. 当AWT决定绘制窗口时(大多数情况下是因为操作系统发送了一条消息告诉它这样做),paintComponent被调用。当它绘制JFrame时,它遍历其中包含的对象树,其中包括你的Line实例,因为你使用jf.add(new Line())添加了它。在每个对象上都会调用paintComponent方法。

  2. 它不接受空参数。

  3. 当AWT调用paintComponent时,它会传递一个从Graphics继承而来的具体类的实例。

签名paintComponent(Graphics g)并没有严格要求参数必须是Graphics类型,而是说它应该是Graphics或任何从Graphics继承的类的类型。另一种看待它的方式是说任何从Graphics继承的类也是Graphics类型。


0

在你的小程序中绘制线条、形状、字符和图像到屏幕上。Java 中大部分的图形操作都是在 Graphics 类 中定义的方法。你不需要创建 Graphics 的实例就可以在你的小程序中绘制任何东西;在你的小程序的 paint() 方法中,你会得到一个 Graphics 对象。通过在该对象上绘制,你可以将其绘制到你的小程序上并在屏幕上显示结果。Graphics 类是 java.awt 包的一部分,因此如果你的小程序进行任何绘画(通常都会),请确保在 Java 文件开头导入该类。


0
你需要知道的是,paintComponent() 方法只有在第一次由 AWT 调用时才会被调用,而不是由你调用。但是,你可以使用方法 "repaint()",因为它在内部调用 paintComponent() 来更新图形。此外,图形对象是由 Graphics 的内部子类创建的。因此,在调用 paintComponent() 之前,AWT 创建了一个类扩展 Graphics 的对象(假设为 g)。之后,AWT 通过传递 "g" 对象调用你定义的 paintCompoent()。
这就像 actionPerformed() 方法在监听器上工作一样。你只是定义它,但实际上并不知道它在哪里被调用。实际上,这些都是 JVM(Java虚拟机)执行的任务。
jbutton.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent e){
      //Do sth on button click.
   }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接