paintComponent中的初始化不起作用

时间:2012-07-07 15:31:34

标签: java swing

我正在做一些练习来理解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);
    }
}

4 个答案:

答案 0 :(得分:5)

其他人帮助建议了检测和避免NullPointerException的方法。不幸的是,当调用paintComponent()的实现时,你不能依赖。相反,

  • 根据当前寡妇的大小确定所需的几何图形;在下面的示例中调整窗口大小,以查看yellow似乎粘贴到右下角。

  • 由于MyPanel不包含自己的组件,因此您应该覆盖getPreferredSize(),因为@nIcE cOw显示here

  • 使用pack()调整封闭式Window的大小。

  • 构建于event dispatch thread

附录:我无法理解为什么要覆盖方法 getPreferredSize()

JComponent的子类覆盖getPreferredSize(),以便pack()可以调整Window的大小以适合其子组件的首选大小和布局。“这样,您就不必担心用户是否有不同的字体,例如。 MyPanel只是绘制几何形状,所以你是首选大小的老板。正如here所述,演示可能会使用setPreferredSize()以方便使用,但您应该了解这样做的局限性。

enter image description here

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

答案 1 :(得分:2)

您从未在任何地方致电rect.initRect();,这就是您在NullPointerException处收到与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()内写一个intiRect(),那么在paintComponent(...)方法本身之前会调用给出错误的行。因此,在我看来,您必须从paintComponent(...)方法中取出该逻辑并将其保留在其他位置,否则如果您不需要它们,则删除这些线。

答案 2 :(得分:1)

您正在尝试访问aba.rect.blue构造函数中的aba.rect.yellowDisegno,但是在调用RectArea.paintComponent之前不会对其进行初始化,因此会抛出NPE。

答案 3 :(得分:1)

你确定你的代码给出了NullPointerException ....... ??

因为当我运行你的代码时,它工作得很好......

<强>输出:

ok
484-442