簡體   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