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.blue
和aba.rect.yellow
,但是在调用RectArea.paintComponent
之前不会初始化RectArea.paintComponent
,因此它会抛出NPE。
你确定你的代码给出了NullPointerException ……. ??
因为当我运行你的代码时,它工作得很好……
输出:
ok 484-442