重写JFrame的paint方法绘制背景后JLabel不显示的问题
问题:重写JFrame的paint方法添加背景图后,JLabel无法显示
我通过重写JFrame的paint方法添加了背景图片,但运行时添加的JLabel无法显示。移除背景图片后JLabel可正常显示,但我需要同时保留背景图与JLabel。
相关代码
public class startingPage extends JFrame { private JPanel contentPane; private String audioFileName = "bg-music.wav"; private String imagePath = "truck_850x300_mining_island.png"; private String logo = "explore_with_mine.png"; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { startingPage frame = new startingPage(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public startingPage() { initComponents(); createEvents(); playAudio(); } public void playAudio() { // TODO Auto-generated method stub try { File audioPath = new File(audioFileName); programManager.stream = AudioSystem.getAudioInputStream(audioPath); programManager.clip = AudioSystem.getClip(); programManager.clip.open(programManager.stream); programManager.clip.start(); } catch(Exception e) { e.printStackTrace(); } } public void createEvents() { } public void initComponents() { setTitle("Explore With Mine"); setIconImage(Toolkit.getDefaultToolkit().getImage(startingPage.class.getResource("/exploreWithMine/resources/logo.png"))); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); setBounds(400, 200, 720, 480); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JButton btnNewButton = new JButton("START"); btnNewButton.setBounds(262, 299, 177, 58); btnNewButton.setBackground(Color.LIGHT_GRAY); btnNewButton.setForeground(new Color(165, 42, 42)); btnNewButton.setFont(new Font("Tahoma", Font.BOLD, 42)); contentPane.add(btnNewButton); JLabel lblNewLabel = new JLabel("TESTING"); lblNewLabel.setFont(new Font("Tahoma", Font.PLAIN, 16)); lblNewLabel.setBounds(10, 10, 146, 43); contentPane.add(lblNewLabel); } public void paint(Graphics g) { g.drawImage(new ImageIcon(imagePath).getImage(),-70,90, null); } }
问题原因
重写JFrame的paint方法时,没有调用父类的super.paint(g),导致JFrame的子组件(JLabel、JButton等)的绘制逻辑被跳过,无法显示。另外,每次在paint方法中创建ImageIcon会重复加载图片,影响性能。
解决方案
方案一:修复现有paint方法
在paint方法中先调用父类方法绘制子组件,再绘制背景图,同时提前加载图片避免重复IO操作:
private Image backgroundImage; public startingPage() { // 提前加载背景图 try { backgroundImage = ImageIO.read(new File(imagePath)); } catch (IOException e) { e.printStackTrace(); } initComponents(); createEvents(); playAudio(); } @Override public void paint(Graphics g) { super.paint(g); // 先绘制子组件 if(backgroundImage != null){ g.drawImage(backgroundImage, -70, 90, this); // 最后绘制背景图 } }
方案二:推荐方案——重写JPanel的paintComponent
更符合Swing组件层次设计的做法是,自定义JPanel绘制背景,再将其作为内容面板:
public class startingPage extends JFrame { private JPanel contentPane; private String audioFileName = "bg-music.wav"; private String imagePath = "truck_850x300_mining_island.png"; private String logo = "explore_with_mine.png"; private Image backgroundImage; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { startingPage frame = new startingPage(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } public startingPage() { // 提前加载背景图 try { backgroundImage = ImageIO.read(new File(imagePath)); } catch (IOException e) { e.printStackTrace(); } initComponents(); createEvents(); playAudio(); } public void playAudio() { try { File audioPath = new File(audioFileName); programManager.stream = AudioSystem.getAudioInputStream(audioPath); programManager.clip = AudioSystem.getClip(); programManager.clip.open(programManager.stream); programManager.clip.start(); } catch(Exception e) { e.printStackTrace(); } } public void createEvents() { } public void initComponents() { setTitle("Explore With Mine"); setIconImage(Toolkit.getDefaultToolkit().getImage(startingPage.class.getResource("/exploreWithMine/resources/logo.png"))); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); setBounds(400, 200, 720, 480); // 创建自定义背景面板 contentPane = new JPanel(){ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if(backgroundImage != null){ g.drawImage(backgroundImage, -70, 90, this); } } }; contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JButton btnNewButton = new JButton("START"); btnNewButton.setBounds(262, 299, 177, 58); btnNewButton.setBackground(Color.LIGHT_GRAY); btnNewButton.setForeground(new Color(165, 42, 42)); btnNewButton.setFont(new Font("Tahoma", Font.BOLD, 42)); contentPane.add(btnNewButton); JLabel lblNewLabel = new JLabel("TESTING"); lblNewLabel.setFont(new Font("Tahoma", Font.PLAIN, 16)); lblNewLabel.setBounds(10, 10, 146, 43); contentPane.add(lblNewLabel); } }
内容的提问来源于stack exchange,提问作者Saturo Gojo
相关产品推荐
相关产品推荐

