paintComponent中的图像仅在调整窗口大小后显示

我想使用paintComponent(Graphics g)使用for循环绘制一些图像。 但是,JFrame只显示为白色屏幕,它只显示调整窗口大小后的黑色背景和图像。

 import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import javax.imageio.*; import java.awt.geom.*; import java.awt.image.BufferedImage; import java.awt.Graphics; import java.util.Scanner; public class SimpleAdventure { private JFrame frame; private CardLayout cards; private Container c; private DrawPanel1 gamepanel; private BufferedImage greentiles, pinktiles, sandtiles, charsprites; private Image left1, right1, left2, right2, front; private Image pinkbg, greenbg, sandbg; private Image pinktop, greentop, sandtop; private int charx, chary; public SimpleAdventure() {} public static void main (String [] args) { SimpleAdventure retro = new SimpleAdventure(); retro.run(); } public void run() { frame = new JFrame("Simple Adventure"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(576, 576); frame.setVisible(true); // frame.setResizable(false); getImage(); c = frame.getContentPane(); cards = new CardLayout(); c.setLayout(cards); gamepanel = new DrawPanel1(); gamepanel.setBackground(Color.black); c.add(gamepanel, "Panel 1"); } public void getImage() { try { greentiles = ImageIO.read(new File("greenTiles.png")); pinktiles = ImageIO.read(new File("pinkTiles.png")); sandtiles = ImageIO.read(new File("sandTiles.png")); charsprites = ImageIO.read(new File("charactersheet.png")); } catch(IOException e) { e.printStackTrace(); } left1 = charsprites.getSubimage(18, 0, 6, 6); left2 = charsprites.getSubimage(24, 0, 6, 6); right1 = charsprites.getSubimage(0, 0, 6, 6); right2 = charsprites.getSubimage(6, 0, 6, 6); front = charsprites.getSubimage(12, 0, 6, 6); greenbg = greentiles.getSubimage(240, 0, 16, 16); sandbg = sandtiles.getSubimage(240, 0, 16, 16); pinkbg = pinktiles.getSubimage(240, 0, 16, 16); greentop = greentiles.getSubimage(224, 0, 16, 16); sandtop = sandtiles.getSubimage(224, 0, 16, 16); pinktop = pinktiles.getSubimage(224, 0, 16, 16); } class DrawPanel1 extends JPanel implements KeyListener { // private BottomPanel lower; public DrawPanel1() { /*this.setLayout(new BorderLayout()); lower = new BottomPanel(); this.add(lower, BorderLayout.SOUTH);*/ addKeyListener(this); } public void paintComponent(Graphics g) { super.paintComponent(g); for(int i = 0; i < 7; i++) { g.drawImage(greentop, 0 + (i * 96), 480, 96, 96, this); } System.out.println("check"); } public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } } } 

您需要调用frame.pack()来执行初始布局。 自动调整窗口大小会导致布局被修复,但frame.setSize(...)不会*。

frame.setVisible(true)移动到run方法的末尾(即在构造完所有UI元素之后)并将frame.pack()放在frame.setVisible(true)之前。 (感谢Hovercraft和MadProgrammer指出这一点)

*至少,如果框架不可见则不会。 如果框架已经可见,它可能会起作用; 试试吧,看看。

编辑:现在我重新阅读了javadoc,你可能根本不想pack – 它会为你调整框架的大小。 如果不对它进行测试,我猜想移动setVisible到底会有效; 如果没有,则使用revalidate而不是pack来使布局引擎运行。

编辑2:现在我重新读取了javadoc,如果窗口不可显示, setVisible将validation窗口。 因此,您不需要显式调用revalidatesetSize 将使组件无效 ,但不会重新validation它。

TL; DR:值得一提的是如何validationSwing中的validation和可显示性,这样你就不会犯错误。

只有在构建UI后才调用setVisible

 public void run() { frame = new JFrame("Simple Adventure"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(576, 576); // frame.setResizable(false); getImage(); c = frame.getContentPane(); cards = new CardLayout(); c.setLayout(cards); gamepanel = new DrawPanel1(); gamepanel.setBackground(Color.black); c.add(gamepanel, "Panel 1"); // Lucky last... frame.setVisible(true); } 

否则,您需要重新validation框架