Java J面板漆

Java Jpanel paint

我有这个 java jpanel 的例子:

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

    public class JavaGame extends JFrame {

    public JavaGame() {
    setTitle("Game");
    setSize(500,500);
    setResizable(false);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void paint(Graphics g) {
    g.drawString("Hello World!",75,75);
    }

    public static void main(String[] args) {

    new JavaGame();

    }

    }

因此,我们只需定义方法 paint,然后创建新的 JavaGame 对象,它就会调用 paint。我不明白两件事:

  1. new JavaGame() - shouldn't we assign a object name like obj = new JavaGame()?
  2. Shouldn't we call the method paint like obj.paint()?

我对OOP有基本的了解,但是这段代码让我很困惑。有人可以给我解释一下吗?

您创建了对象 new JavaGame() 而没有将其分配给任何变量,仅此而已。

Swing 渲染和事件线程启动并处理应用程序的其余部分。

我不确定垃圾收集器为什么不捡起并结束它,但我已经这样做了很长时间并且工作正常。

new JavaGame() - shouldn't we assign a object name like obj = new JavaGame()?

这涉及到对象和引用变量之间的重要区别。这里最重要的是创建一个 JavaGame 对象,您可以通过 new JavaGame() 来完成。由于此对象在其构造函数中显示 JFrame,因此只需创建对象即可创建显示,无需将对象分配给任何变量。

请注意,对象 没有名称,但某些 变量 有名称。例如,如果您创建了一个 Foo 对象,并将其分配给一个 bar 变量:

Foo bar = new Foo();

但随后将同一对象分配给 baz 变量:

Foo baz = bar;

bar 和 baz 指的是完全相同的 Foo 对象。那么对象的名称是什么?同样,对象名称不存在且毫无意义。


Shouldn't we call the method paint like obj.paint()?

正如 MightyPork(对他来说 1+)所指出的那样,绘制方法 由 JVM 调用,不应由您直接调用。您可以建议通过调用 repaint() 来调用它,但您几乎不应该直接调用它或 paintComponent(...) 方法。


其他问题:

  • 在 Swing 中绘制时,不要忘记在您自己的重写中调用超级绘制方法。否则,组件将不会进行自己的内务绘画,并且您将打破绘画链,这意味着绘画容器中的组件可能无法正确绘画或根本无法绘画。
  • 一般来说,您会不想直接在 JFrame 中绘制,因为 JFrame 负责许多关键组件,如果您搞砸了某些东西,GUI可能会搞砸。
  • 更好的方法是在 JPanel 的 paintComponent 方法中绘制,然后在 JFrame 中显示该 JPanel。
  • 查看教程以了解所有血腥但非常重要的细节:

编辑 你问:

So, when use API, we just "fill" with code the methods in the class, and the JVM will know when to call these methods?

最常见的 Swing 图形是 "passive"。这意味着您将组件设置为以某种方式绘制,但您不会主动绘制它。而是 JVM(Java 虚拟机——运行您的 Java 程序的代码)为您绘图。如果你想做动画,通常你会改变一些位置变量,例如 xPosition 和 yPosition int 变量,然后在你的 JPanel 的 paintComponent(Graphics g) 方法中使用这些变量。因此,如果您在 Swing 计时器中更改这些变量所持有的值,然后在值更改后调用 repaint(),JVM 将(通常)使用新值重新绘制您的组件。


在 JPanel 中显示绘图并显示非常简单的动画的更复杂的示例:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

// draw in a JPanel, not a JFrame
public class SimpleAnimation extends JPanel {
   private static final int OVAL_WIDTH = 40;
   private static final int TIMER_DELAY = 50;
   private static final int PREF_W = 800;
   private static final int PREF_H = PREF_W;
   private int xPosition = 0;
   private int yPosition = 0;

   public SimpleAnimation() {
      // start my timer here
      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   @Override
   protected void paintComponent(Graphics g) {
      // call the super method so that the JPanel
      // can do its own house-keeping graphics first
      super.paintComponent(g);

      // I do this to so that my graphics are smooth 
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(Color.red);

      // use xPosition and yPosition to place my oval
      g2.fillOval(xPosition, yPosition, OVAL_WIDTH, OVAL_WIDTH);
   }

   // so our GUI will be big enough to see
   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   // class used by the Swing Timer to drive animation
   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         // change xPosition and yPosition
         xPosition++;
         yPosition++;

         // and call repaint
         repaint();
      }
   }

   // a method to be called in our Runnable
   private static void createAndShowGui() {
      SimpleAnimation mainPanel = new SimpleAnimation();

      JFrame frame = new JFrame("SimpleAnimation");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      // this is used to make sure that all Swing code
      // is started on the Swing event thread.
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
  1. 您不需要对象名称。当您使用 new 时,将调用构造函数,创建框架。
  2. Paint 会在需要时被调用。查看 this answer