paintComponent中的初始化不起作用

我正在做一些练习来理解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.blue构造函数中的aba.rect.blueaba.rect.yellow ,但是在调用RectArea.paintComponent之前不会初始化RectArea.paintComponent ,因此它会抛出NPE。

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

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

输出:

 ok 484-442