4

Java と Swing API を理解するための演習を行っています。Disegno コンストラクターに nullPointerException があるのはなぜですか? 2 つの長方形の座標を出力したいのですが、初期化されていないようです。

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);
    }
}
4

4 に答える 4

5

を検出して回避する方法を提案した人もいますNullPointerException。残念ながら、の実装がいつ呼び出されるかを当てにすることはできませんpaintComponent()。その代わり、

  • 現在のウィンドウのサイズの関数として必要なジオメトリを決定します。下の例のウィンドウのサイズを変更して、右下隅に固定yellowされているように見えることを確認してください。

  • @nIcE cOw がここにMyPanel示すように、独自のコンポーネントが含まれていないため、オーバーライドする必要があります。getPreferredSize()

  • pack()囲んでいる のサイズを変更するために使用しますWindow

  • イベント ディスパッチ スレッドに基づいて構築します。

補遺:メソッドをオーバーライドする理由がわかりません getPreferredSize()

「サブコンポーネントの優先サイズとレイアウトに合わせて」サイズを変更できるJComponentオーバーライドのサブクラス。そうすれば、たとえば、ユーザーが別のフォントを使用していても心配する必要はありません。幾何学的形状を描くだけなので、好みのサイズのボスです。ここで説明したように、デモでは便宜上 を使用できますが、その制限を理解する必要があります。getPreferredSize()pack()WindowMyPanelsetPreferredSize()

ここに画像の説明を入力

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);
        }
    }
}
于 2012-07-07T18:19:29.517 に答える
2

rect.initRect();どこにも電話したことがないためNullPointerException、 at them に関連するエラーが発生しますSystem.out.println() lines。各クラス内で使用する理由はpanelObject.setVisible(true)、最初にそれらを に追加し、JPanel単に を呼び出すだけです。ここで、期待どおりに動作する、上記のものを使用して変更されたコードを確認します。setVisible(...)JFrame

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);
    }
}

System.out.println()内にa を書くと、エラーが発生している行がメソッド自体intiRect()の前に呼び出されていることがわかります。paintComponent(...)したがって、そのロジックをpaintComponent(...)メソッドから取り出して別の場所に保持するか、不要な場合はそれらの行を削除する必要があるように私には思えます。

于 2012-07-07T17:01:22.820 に答える
1

コードでNullPointerExceptionが発生したことを確認してください.......??

私があなたのコードを実行したとき、それはうまくいったので...

出力:

ok
484-442
于 2012-07-07T16:28:36.600 に答える
1

コンストラクターでaba.rect.blueandaba.rect.yellowにアクセスしようとしていますが、これらはが呼び出されるまで初期化されないため、NPE がスローされます。DisegnoRectArea.paintComponent

于 2012-07-07T15:42:27.880 に答える