How to paint an image over the JPanel and add components in it

*爱你&永不变心* 提交于 2019-12-02 12:13:03

问题


My application is a simple game of Brick Breaker. In order to paint the visuals of the application I'm using the paintComponent method. The application also has several buttons that are added using the following code:

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

The issue Im having is that the buttons are being added, but also they seem to be painted in the background image of the application:

The buttons on the right dont work, and are just images. Any clue how to fix this issue.


回答1:


Use below code snippet for your reference:

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

using paint component is not good practice so its always better to extent your component UI class from basic component UI class and override the paint() method. This way swing will take care of all the rendering / re-rendering part and your component(s) added to panel will be visible too.

Now, I strongly recommend that you stop and go have a read through:

  • Performing Custom Painting
  • Painting in AWT and Swing
  • BufferStrategy and BufferCapabilities
  • How to Use Layered Panes



回答2:


The primary issue comes down to...

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

The Graphics context passed to the paintComponent method is a shared resource, all the components rendered within the paint pass will use it. This means that any changes you make to it will also affect them. You should be especially aware of transformations (like translate and scale).

A general practice is to make a snapshot of the state of Graphics context before you use it, this allows you to make changes to the copy with affecting the original, something like...

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

The other issue is subPanel.setBackground(Constants.CLEAR);. I'm assuming that this is a alpha based color. Swing component's don't support alpha based colors, they are either fully opaque or fully transparent (although you can fake it). This is controlled through the use of setOpaque

Now, I strongly recommend that you stop and go have a read through:

  • Performing Custom Painting
  • Painting in AWT and Swing


来源:https://stackoverflow.com/questions/51824808/how-to-paint-an-image-over-the-jpanel-and-add-components-in-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!