paintComponent有时只调用

时间:2013-09-19 00:39:16

标签: java swing jpanel paint paintcomponent

我正在创建一个程序,它接受一个二维整数数组,并使用它的数据以数组中指定的排列方式将图块绘制到屏幕上。在不修改任何代码的情况下,程序将在5次中执行大约4次。其他时候自定义JPanel不会显示任何内容。在各个地方插入system.out.print()后,我确定它是由paintComponent方法引起的,当没有显示任何内容时。显然,当瓷砖完美显示时会调用它。我似乎无法找到这种不一致的根源。为什么它会在大多数时间内起作用而不是偶尔起作用?

它被称为Isopanel,因为它最终会以等距形式显示瓷砖。 0s等于水砖,1s等于砂砖。

JPanel Class

 public class IsoPanel extends JPanel
    {
    private ArrayList <BufferedImage> tiles;
    private int[][] leveldata = 
        {
             {0,0,0,0,0,0,0,0,0,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,1,1,1,1,1,1,1,1,0},
             {0,0,0,0,0,0,0,0,0,0}
        };
    public IsoPanel()
    {
        tiles = new ArrayList<BufferedImage>();
        tiles.add(Frame.loadImage("water.png"));
        tiles.add(Frame.loadImage("sand.png"));
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        for (int i=0; i<10; i++) 
        {
             for (int j=0; j<10; j++)
             {
              int x = j * 50;
              int y = i * 50;
              int tileType = leveldata[i][j];
              placeTile(tileType, x, y, g);
             }
        }
    }

    public void placeTile (int tile,int x,int y, Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        g2.drawImage(tiles.get(tile), null, x, y);  
    }
}

和JFrame类:

public class Frame extends JFrame
    {
    public Frame()
    {
        super ("Iso");
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(0,0,screenSize.width, screenSize.height);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);           
        BorderLayout bord = new BorderLayout();
        setLayout(bord);            
        IsoPanel iso = new IsoPanel();
        add(iso,BorderLayout.CENTER);
        GridLayout grid = new GridLayout(1,1);
        iso.setLayout(grid);
        iso.setVisible(true);
    }

    public static BufferedImage loadImage(String filename)
    {
        {
            try
            {
            return ImageIO.read(new File(System.getProperty( "user.dir" )+"/src/"+filename));
            }
            catch(IOException e)
            {
            }
        }
        return null;
    }

    public static void main(String[] args)
    {
        Frame one = new Frame();
    }    
}

1 个答案:

答案 0 :(得分:3)

主要问题是您在初始化子组件之前在帧上调用setVisible。这是框架如何准备状态的已知问题......

所以,而不是......

public Frame()
{
    /*...*/
    setVisible(true);

    /*...*/
    add(iso,BorderLayout.CENTER);
}

...试

public Frame()
{
    /*...*/
    add(iso,BorderLayout.CENTER);

    /*...*/
    setVisible(true);
}

其他...

  • 你不应该抛弃你的例外。至少,您应该打印例外或记录它。
  • 绘制图像时应使用ImageObsever。您应该尝试使用g2.drawImage(tiles.get(tile), null, x, y);而不是g2.drawImage(tiles.get(tile), x, y, this);。图像并不总是处于立即渲染的状态,这为组件提供了一种对图像状态变化作出反应并自动重新绘制的方法......
  • 即使您要设置父框架的大小,您的IsoPanel组件也应该以覆盖getPreferredSize的形式提供布局提示,这样您只需pack主窗口。这可以降低不同平台上不同框架边框尺寸和外观设置的可能性。
  • 您可以查看Initial Threads以及使用EventQueue.invokeLater启动您的用户界面的重要信息
  • System.getProperty( "user.dir" )+"/src/"+filename)看起来应该引用嵌入式资源......