如何在JPanel上绘制图像并在其中添加组件

我的应用程序是一个简单的Brick Breaker游戏。 为了绘制应用程序的视觉效果,我正在使用paintComponent方法。 该应用程序还有几个使用以下代码添加的按钮:

levelMenu = new JPanel() { @Override public void paintComponent(Graphics g) { super.paintComponent(g); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); double scale = screenSize.getHeight()/1080; Graphics2D g2d = (Graphics2D) g; g2d.scale(scale, scale); g2d.drawImage(background, 0, 0, null); } }; levelMenu.setLayout(new FlowLayout()); JPanel subPanel = new JPanel(new GridLayout(20, 2, 10, 10)); subPanel.setBackground(Constants.CLEAR); subPanel.add(new JLabel()); subPanel.add(new JLabel()); for (JButton level: levelList) { subPanel.add(level); } subPanel.add(new JLabel()); subPanel.add(back); levelMenu.add(subPanel); this.add(levelMenu); 

我遇到的问题是正在添加按钮,但它们似乎也在应用程序的背景图像中绘制: 示例屏幕截图

右侧的按钮不起作用,只是图像。 任何线索如何解决这个问题。

使用下面的代码段作为参考:

 import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicPanelUI; class MyPanelUI extends BasicPanelUI { public void paint(Graphics g, JComponent c) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Graphics2D g2d = (Graphics2D) g; Image img = toolkit.getImage("/usr/share/backgrounds/warty-final-ubuntu.png"); g2d.drawImage(img, 0, 0, null); } public Dimension getPreferredSize(JComponent c) { return super.getPreferredSize(c); } } public class PanelBGTest { public static void main(String[] args) { JFrame frame = new JFrame(); JPanel panel = new JPanel(); panel.setUI(new MyPanelUI()); panel.setLayout(new FlowLayout()); panel.add(new JButton("This is button")); SwingUtilities.updateComponentTreeUI(frame); frame.add(panel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 400); frame.setVisible(true); } } 

使用paint组件并不是一个好习惯,因此最好从基本组件UI类扩展组件UI类并覆盖paint()方法。 这样摆动将处理所有渲染/重新渲染部分,并且添加到面板的组件也将可见。

现在,我强烈建议您停下来阅读:

  • 执行自定义绘画
  • 在AWT和Swing中绘画
  • BufferStrategy和BufferCapabilities
  • 如何使用分层窗格

主要问题归结为……

 Graphics2D g2d = (Graphics2D) g; g2d.scale(scale, scale); g2d.drawImage(background, 0, 0, null); 

传递给paintComponent方法的Graphics上下文是一个共享资源,在paint pass中呈现的所有组件都将使用它。 这意味着您对其所做的任何更改也会影响它们。 你应该特别注意转换(比如translatescale )。

一般的做法是在使用之前制作Graphics上下文状态的快照,这允许您对影响原始的副本进行更改,例如……

 Graphics2D g2d = (Graphics2D) g.create(); g2d.scale(scale, scale); g2d.drawImage(background, 0, 0, null); g2d.dispose(); 

另一个问题是subPanel.setBackground(Constants.CLEAR); 。 我假设这是一种基于alpha的颜色。 Swing组件不支持基于alpha的颜色,它们要么完全不透明要么完全透明(尽管你可以伪造它)。 这是通过使用setOpaque来控制的

现在,我强烈建议您停下来阅读:

  • 执行自定义绘画
  • 在AWT和Swing中绘画