繁体   English   中英

Java Jpanel油漆

[英]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()-我们是否应该分配一个对象名称,例如obj = new JavaGame()?
  2. 我们不应该像obj.paint()那样调用paint方法吗?

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

new JavaGame()-我们是否应该分配一个对象名称,例如obj = new JavaGame()?

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

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

Foo bar = new Foo();

但是然后将相同的对象分配给baz变量:

Foo baz = bar;

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


我们不应该像obj.paint()那样调用paint方法吗?

正如MightyPork(对他而言为1+)所指出的那样,paint方法是由JVM调用 ,不应由您直接调用。 您可以建议通过调用repaint()调用它,但几乎永远不要直接调用它,也不要直接调用paintComponent(...)方法。


其他事宜:

  • 在Swing中绘画时,请不要忘记在自己的替代中调用super paint方法。 否则,该组件将不会自己进行内部绘画,您将中断绘画链,这意味着由已绘制容器容纳的组件可能无法正确绘制或完全未绘制。
  • 通常,您将希望直接在JFrame中绘制,因为JFrame负责许多关键组件,并且如果您弄乱了某些内容,则可能会弄乱GUI。
  • 更好的方法是绘制一个JPanel的paintComponent方法,然后在JFrame中显示该JPanel。
  • 查看教程,了解所有血腥但非常重要的细节:

编辑你问:

因此,当使用API​​时,我们只需在代码中“填充”类中的方法,JVM就会知道何时调用这些方法?

大多数情况下,Swing图形是“被动的”。 意味着您将组件设置为以某种方式绘制,但您自己不会主动进行绘制。 而是由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();
         }
      });
   }
}

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

Swing渲染和事件线程开始运行,并照顾了应用程序的剩余生命。

我不确定垃圾收集器为什么不捡起并结束它,但是我已经用这种方式做了很长时间了,并且效果很好。

  1. 您不需要对象名称。 当您使用new ,将调用构造函数,从而创建框架。
  2. Paint会在需要时被调用。 看看这个答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM