【问题标题】:How to paint an image over the JPanel and add components in it如何在 JPanel 上绘制图像并在其中添加组件
【发布时间】:2018-08-13 14:34:23
【问题描述】:

我的应用程序是一个简单的 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);

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

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

【问题讨论】:

    标签: java swing paintcomponent


    【解决方案1】:

    主要问题归结为...

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

    传递给paintComponent 方法的Graphics 上下文是共享资源,所有在绘制过程中呈现的组件都将使用它。这意味着您对其所做的任何更改也会影响它们。您应该特别注意转换(如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来控制的

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

    【讨论】:

      【解决方案2】:

      使用下面的代码 sn-p 供您参考:

      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() 方法总是更好。这样,swing 将处理所有渲染/重新渲染部分,并且您添加到面板的组件也将可见。

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

      【讨论】:

      • 我不会使用 Toolkit.getImage,它是有限的,我不会在每次调用paint时都加载图像——效率低下,事实上,图像参考应该来自组件(或被设置为 UI 委托的属性)
      • “使用绘画组件不是好的做法” - 真的,谁说的?您链接到的教程都支持相反的主张。除非您打算提供不同的外观和感觉委托,否则开发一个全新的 UI 委托是没有意义的
      • ? 你真的需要逐字引用my previous post的最后一部分
      • 同意在paint方法中加载图像。您之前帖子中的链接很有帮助,因此必须传递信息。无论如何,每个人都有自己的观点。但是,如果您想使用绘画组件,那么在这种情况下,您必须在少数地方手动调用重绘/绘画(这实际上取决于具体情况)。如果您只为 UI 绘制器类提供绘制方法,则 Swing 只负责绘制。
      • 实际上 Swing 并没有“只处理”绘画 - UI 委托 paint 方法由组件 paintComponent 方法调用,因此您仍然需要调用 repaint触发新的油漆通道
      猜你喜欢
      • 2012-10-17
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 2011-01-17
      • 1970-01-01
      相关资源
      最近更新 更多