简体   繁体   English

paintComponent有时仅被调用

[英]paintComponent only called sometimes

I am making a program that takes a two dimensional integer array and uses its data to draw tiles to the screen in the arrangement specified in the array. 我正在制作一个程序,该程序需要一个二维整数数组,并使用其数据按照数组中指定的排列方式将图块绘制到屏幕上。 Without modifying any of the code, the program will execute fine about 4 out of 5 times. 在不修改任何代码的情况下,该程序将执行5次中的大约4次。 Other times the custom JPanel will not display anything. 有时自定义JPanel将不显示任何内容。 After inserting system.out.print() in various places I have determined that it is caused by the paintComponent method not being called when nothing is displayed. 在不同位置插入system.out.print()后,我确定这是由于在什么都不显示时未调用paintComponent方法引起的。 Obviously it is called when the tiles are displayed perfectly. 显然,当磁贴完美显示时会调用它。 I can't seem to find the source of this inconsistency. 我似乎找不到这种不一致的根源。 Why would it work the majority of the time and not every once in a while? 为什么它会在大多数时间而不是每隔一段时间工作?

Its called Isopanel because it will eventually display tiles in an isometric formation. 之所以称为Isopanel,是因为它将最终以等轴测图形式显示图块。 0s equate to water tiles and 1s equate to sand tiles. 0s等于水砖,1s等于沙砖。

JPanel Class JPanel类别

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

and JFrame class: 和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();
    }    
}

The main issue is the fact that you are calling setVisible on your frame before you've finished initialising the child components. 主要问题是,在完成子组件的初始化之前,您正在框架上调用setVisible This is a known issue with how frame prepares it's state... 这是框架如何准备状态的一个已知问题...

So, instead of... 所以,而不是...

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

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

Try... 尝试...

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

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

Additional... 额外...

  • You shouldn't be throwing away your exceptions. 您不应该丢弃异常。 At the very least, you should be printing the exception or logging it. 至少,您应该打印异常或记录它。
  • You should be using an ImageObsever when drawing images. 绘制图像时应使用ImageObsever Instead of g2.drawImage(tiles.get(tile), null, x, y); 代替g2.drawImage(tiles.get(tile), null, x, y); , you should try using g2.drawImage(tiles.get(tile), x, y, this); ,您应该尝试使用g2.drawImage(tiles.get(tile), x, y, this); . Images aren't always in state to be rendered immediately, this provides a means for the component to react to changes in the image state and automatically repaint themselves... 图像并不总是处于立即渲染的状态,这为组件提供了一种对图像状态的变化做出反应并自动重新绘制自身的方法。
  • Even though you are setting the size of the parent frame, your IsoPanel component should be providing layout hints in the form of overriding getPreferredSize , allowing you to simply pack the main window. 即使您设置父框架的大小, IsoPanel组件也应该以覆盖getPreferredSize的形式提供布局提示,从而使您可以简单地pack主窗口。 This discounts the possibility of different frame border sizes on different platforms and look and feel settings. 这降低了在不同平台和外观设置上不同边框边框大小的可能性。
  • You may wish to take a look at Initial Threads and the important of using EventQueue.invokeLater to launch your UI 您可能希望看看Initial Threads,以及使用EventQueue.invokeLater启动UI的重要性
  • System.getProperty( "user.dir" )+"/src/"+filename) looks like it should be referencing an embedded resource... System.getProperty( "user.dir" )+"/src/"+filename)看起来应该引用嵌入式资源...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM