簡體   English   中英

paintComponent中的初始化不起作用

[英]Initialization in paintComponent doesn't work

我正在做一些練習來理解Java和Swing API。 為什么在Disegno構造函數中有nullPointerException? 我想打印兩個矩形的坐標,但它們似乎沒有初始化。

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

public class Disegno extends JFrame{

    Disegno(){
        this.setSize(500, 500);
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        MyPanel aba = new MyPanel();
        this.setContentPane(aba);
        this.setVisible(true);

        System.out.println(aba.rect.blue.x + "-" + aba.rect.blue.y);
        System.out.println(aba.rect.yellow.x + "-" + aba.rect.yellow.y);
    }

    public static void main(String[] args){
        new Disegno();
    }
}

class MyPanel extends JPanel{

    JPanel up, down;
    RectArea rect;

    MyPanel(){
        this.setLayout(new BorderLayout());

        up = new JPanel();
        this.add(up, BorderLayout.NORTH);
        up.setBackground(Color.red);
        up.setVisible(true);

        down = new JPanel();
        down.setBackground(Color.green);
        this.add(down, BorderLayout.SOUTH);
        down.setVisible(true);

        rect = new RectArea();
        this.add(rect, BorderLayout.CENTER);

        this.setVisible(true);
    }
}

class RectArea extends JPanel{

    Rectangle blue, yellow;
    boolean check = false;

    RectArea(){
        super();
        this.setVisible(true);
    }

    public void initRect(){
        blue = new Rectangle(0, 0, 100, 100);
        yellow = new Rectangle(this.getWidth(), this.getHeight(), 100, 100);
        System.out.println("ok");
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        if(check == false){
            this.initRect();
            check = true;
        }

        System.out.println(this.getWidth() + "-" + this.getHeight());
        g.setColor(Color.blue);
        g.fillRect(blue.x, blue.y, blue.width, blue.height);
        g.setColor(Color.yellow);
        g.fillRect(yellow.x - yellow.width, yellow.y - yellow.height, yellow.width, yellow.height);
    }
}

其他人已經幫助建議了檢測和避免NullPointerException 不幸的是,您不能依賴於何時調用paintComponent()實現。 代替,

  • 根據當前寡婦的大小確定所需的幾何形狀; 在下面的示例中調整窗口的大小,以查看yellow似乎在右下角。

  • 因為MyPanel包含自己的組件,所以應該覆蓋getPreferredSize() ,如@nIcE cOw 在此處所示

  • 使用pack()來調整封閉Window大小。

  • 構建在事件派發線程上

附錄: 我無法理解為什么要重寫方法 getPreferredSize()

JComponent子類重寫getPreferredSize()以便pack()可以調整Window大小“以適合其子組件的首選大小和布局。” 這樣,您就不必擔心用戶是否有不同的字體,例如。 MyPanel只是繪制幾何形狀,所以你是首選大小的老板。 正如這里所討論的,為了方便起見,演示可能會使用setPreferredSize() ,但您應該理解這樣做的局限性。

在此輸入圖像描述

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

/**
* @see https://stackoverflow.com/q/11376272/230513
*/
public class Disegno extends JFrame {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Disegno();
            }
        });
    }

    Disegno() {
        this.setSize(500, 500);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        MyPanel aba = new MyPanel();
        this.add(aba);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    class MyPanel extends JPanel {

        private JPanel up, down;
        private RectArea rect;

        MyPanel() {
            super(new BorderLayout());

            up = new JPanel();
            up.setBackground(Color.red);
            this.add(up, BorderLayout.NORTH);

            rect = new RectArea();
            this.add(rect, BorderLayout.CENTER);

            down = new JPanel();
            down.setBackground(Color.green);
            this.add(down, BorderLayout.SOUTH);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(320, 240);
        }
    }

    class RectArea extends JPanel {

        private Rectangle blue = new Rectangle(0, 0, 100, 100);
        private Rectangle yellow = new Rectangle(0, 0, 100, 100);

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println(this.getWidth() + " x " + this.getHeight());
            g.setColor(Color.blue);
            g.fillRect(blue.x, blue.y, blue.width, blue.height);

            g.setColor(Color.yellow);
            int dx = getWidth() - yellow.width;
            int dy = getHeight() - yellow.height;
            g.fillRect(dx, dy, yellow.width, yellow.height);
        }
    }
}

你從未調用過rect.initRect(); 在任何地方,這就是你在那些System.out.println() lines得到與NullPointerException相關的錯誤的原因。 為什么在每個類中使用panelObject.setVisible(true) ,首先將它們添加到JPanel並簡單地在JFrame上調用setVisible(...) 在這里使用所述的東西觀察您修改過的代碼,按預期工作:

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

public class Disegno extends JFrame{

    Disegno(){
        this.setSize(500, 500);
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
        MyPanel aba = new MyPanel();
        this.setContentPane(aba);
        this.setVisible(true);

        System.out.println(aba.rect.blue.x + "-" + aba.rect.blue.y);
        System.out.println(aba.rect.yellow.x + "-" + aba.rect.yellow.y);
    }

    public static void main(String[] args){
        new Disegno();
    }
}

class MyPanel extends JPanel{

    JPanel up, down;
    RectArea rect;

    MyPanel(){
        this.setLayout(new BorderLayout());

        up = new JPanel();
        this.add(up, BorderLayout.NORTH);
        up.setOpaque(true);
        up.setBackground(Color.red);

        down = new JPanel();
        down.setOpaque(true);
        down.setBackground(Color.green);
        this.add(down, BorderLayout.SOUTH);

        rect = new RectArea();
        rect.initRect();
        this.add(rect, BorderLayout.CENTER);
    }
}

class RectArea extends JPanel{

    Rectangle blue, yellow;
    boolean check = false;

    RectArea(){
        super();
        setOpaque(true);
    }

    public void initRect(){
        blue = new Rectangle(0, 0, 100, 100);
        yellow = new Rectangle(this.getWidth(), this.getHeight(), 100, 100);
        System.out.println("ok");
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        if(check == false){
            this.initRect();
            check = true;
        }

        System.out.println(this.getWidth() + "-" + this.getHeight());
        g.setColor(Color.blue);
        g.fillRect(blue.x, blue.y, blue.width, blue.height);
        g.setColor(Color.yellow);
        g.fillRect(yellow.x - yellow.width, yellow.y - yellow.height, yellow.width, yellow.height);
    }
}

如果你想在intiRect()編寫一個System.out.println() ,那么在paintComponent(...)方法本身之前會調用給你錯誤的行。 所以在我看來,你必須從paintComponent(...)方法中取出那個邏輯並將它保存在其他地方,否則如果你不需要它們就刪除那些行。

您試圖訪問aba.rect.blueaba.rect.yellowDisegno構造,但這些不會被初始化,直到RectArea.paintComponent被調用,所以它拋出一個NPE。

你確定你的代碼給出了NullPointerException ....... ??

因為當我運行你的代碼時,它工作得很好......

輸出:

ok
484-442

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM