0

所以我在这里做一个需要自定义JLayeredPane类的项目。它有两个成员 'ground' 和 'foreground'JPanel和一个 background ( Image) 成员。

它应该显示的方式是应该绘制背景图像,然后在其顶部绘制地面的所有组件,然后在顶点处绘制前景组件。所以前景覆盖了地面,地面覆盖了背景。背景应仅在没有背景Component和前景的地方或在 s 中有透明度的地方显示JPanel

它的绘画功能是这样的:

@Override
public void paint(Graphics g){
   g.drawImage(background, 0, 0, null);
   ground.paint(g.create());
   foreground.paint(g.create());
   g.dispose();
}

但没有这样的事情发生。只是背景图像被绘制,没有其他显示。

我已经使用System.out.println()函数来检查地面和前景是否确实包含组件并且它们确实存在。但他们只是没有表现出来。

有人能帮我一下吗?

4

2 回答 2

1

最重要的问题是您没有调用super.paint,这会阻止以前绘制到Graphics上下文的内容被清除或绘制任何子组件。

要绘制背景,您应该使用paintComponent,它用于绘制组件的背景。

如果您需要在子组件下方绘制,但在背景上方,您仍然应该使用paintComponent,但先绘制背景,然后再绘制下一层。之后将绘制组件paintComponent

在组件上绘画实际上更复杂

详细了解Swing 和 AWT中的自定义绘画和绘画

根据代码片段更新

Screen其中延伸Container,你正在做......

@Override
public void paint(Graphics g) {
    super.paint(g);
    GraphicsUtilities.drawPictureTiled(background, g);
    paintComponents(g);
    g.dispose();
}
  • 不要打电话paintComponentssuper.paint已经这样做了。
  • 不要调用你没有创建dispose的上下文Graphics
  • 根据我所拥有的示例代码的其余部分,您应该从扩展JPanel和覆盖paintComponent。这将允许您放置在组件层下

因为GroundPanelForeGroundPanel都是JPanels,所以没有必要自己画它们。实际上,您可以简单地使用OverlayLayout甚至 aGridBagLayout并将它们直接添加到NestedScreen本身就是容器的...

所以,我剥离了你的示例代码,以便我可以使用丢失的代码作为示例。我有点花哨,只是做了一个JPanel作为暂停屏幕

小马 1小马 2

这一切都是通过简单地使用一个GridBagLayout

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test1001 {

    public static void main(String[] args) {
        new Test1001();
    }

    public Test1001() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    NestedScreen screen = new NestedScreen();
                    screen.setBackgroundLayer(ImageIO.read(getClass().getResource("/Sky.png")));

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(screen);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public interface GraphicsEngineComponents {

    }

    public class NestedScreen extends Screen implements GraphicsEngineComponents {

        GroundPanel ground;
        ForeGroundPanel foreground;
        private PausePane pausePane;

        public NestedScreen() {

            ground = new GroundPanel();
            foreground = new ForeGroundPanel();
            pausePane = new PausePane();

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;

            add(pausePane, gbc);
            add(foreground, gbc);
            add(ground, gbc);

            MouseAdapter handler = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    pausePane.setVisible(!pausePane.isVisible());
                }
            };

            addMouseListener(handler);
            foreground.addMouseListener(handler);
            ground.addMouseListener(handler);

        }

        public GroundPanel getGroundLayer() {
            return ground;
        }

        public ForeGroundPanel getForegroundLayer() {
            return foreground;
        }

        public void setBackgroundLayer(BufferedImage background) {
            super.setBackgroundLayer(background);
        }

        public class GroundPanel extends JPanel {

            public GroundPanel() {
                setOpaque(false);
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.GREEN);
                g.fillRect(0, getHeight() - 200, getWidth(), 200);
            }

        }

        public class PausePane extends JPanel {

            private JLabel label;

            public PausePane() {
                setVisible(false);
                setOpaque(false);
                setBackground(new Color(0, 0, 0, 128));
                setLayout(new GridBagLayout());

                label = new JLabel("Paused");
                label.setHorizontalAlignment(JLabel.CENTER);
                label.setVerticalAlignment(JLabel.CENTER);
                Font font = label.getFont();
                font = font.deriveFont(Font.BOLD, 48f);
                label.setFont(font);
                label.setForeground(Color.WHITE);
                add(label);
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(getBackground());
                g.fillRect(0, 0, getWidth(), getHeight());
            }

        }

        public class ForeGroundPanel extends JPanel {

            private BufferedImage pony;

            public ForeGroundPanel() {
                setOpaque(false);
                try {
                    pony = ImageIO.read(getClass().getResource("/Pony.png"));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (pony != null) {
                    int x = (getWidth() - pony.getWidth()) / 2;
                    int y = getHeight() - 200 - (pony.getHeight() / 2);
                    g.drawImage(pony, x, y, this);
                }
            }

        }
    }

    public class Screen extends JPanel implements GraphicsEngineComponents {

        private BufferedImage background;

        public Screen() {
        }

        @Override
        public String toString() {
            return "Screen{" + "background=" + background + '}';
        }

        public BufferedImage getBackgroundPicture() {
            return background;
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
        }

        protected void setBackgroundLayer(BufferedImage background) {
            if (background != null && background.getHeight() != 0 && background.getWidth() != 0) {
                this.background = background;
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                g.drawImage(background, 0, 0, this);
            }
        }
    }

}

看一下在 AWT 和 Swing 中的绘画执行自定义绘画,以了解绘画在 Swing 中的工作原理。

一个基本的想法是避免使用所有这些复合或嵌套组件,而是创建一个引擎,可以将图层直接绘制到Graphics上下文上,甚至BufferedImage可以绘制到可以绘制到单个组件上的引擎......

于 2014-03-31T20:44:34.363 回答
0

有几种方法可以做到这一点。我只介绍一种方式。

  • 创建一个背景面板,您可以在其中绘制背景图像(在下面的示例中,BackgroundPanel图像仅作为 forresty 背景)。将该面板设置为框架的内容窗格。

  • 创建另一个地面面板,您还可以在其中绘制一些东西(在下面的示例中,如果它只GroundPanel绘制了兔子兔子的图像。

  • 创建前景面板并将其添加到地面面板。您可以将前景组件添加到其中。(在下面的例子中,前景图像是草山,我还给它添加了一个按钮

  • 所有面板的 opaque 属性都应设置为 false,以允许其后面的面板以任何透明度显示。

在此处输入图像描述

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class ThreeTier {

    public static final int DIM_WIDTH = 600;
    public static final int DIM_HEIGHT = 400;

    private BufferedImage backgroundImage;
    private BufferedImage groundImage;
    private BufferedImage foregroundImage;

    public ThreeTier() {
        initImages();
        JFrame frame = new JFrame();
        frame.setContentPane(new BackgroundPanel());
        frame.add(new GroundPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void initImages() {
        try {
            backgroundImage = ImageIO.read(getClass().getResource("/resources/background.png"));
            foregroundImage = ImageIO.read(getClass().getResource("/resources/foreground.png"));
            groundImage = ImageIO.read(getClass().getResource("/resources/bugsBunny.png"));
        } catch (IOException ex) {
            Logger.getLogger(ThreeTier.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    class BackgroundPanel extends JPanel {

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(backgroundImage, 0, 0, DIM_WIDTH, DIM_HEIGHT, this);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(ThreeTier.DIM_WIDTH, ThreeTier.DIM_HEIGHT);
        }
    }

    class GroundPanel extends JPanel {

        private static final String RIGHT_ACTION = "rightAction";
        private int imageX = 50;
        private int imageY = 140;

        public GroundPanel() {
            setOpaque(false);
            add(new ForegroundPanel());

            InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke("RIGHT"), RIGHT_ACTION);
            getActionMap().put(RIGHT_ACTION, new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    if (imageX >= DIM_WIDTH) {
                        imageX = 0 - groundImage.getWidth();
                        repaint();
                    } else {
                        imageX += 10;
                        repaint();
                    }

                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(groundImage, imageX, imageY, groundImage.getWidth(), groundImage.getHeight(), this);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(ThreeTier.DIM_WIDTH, ThreeTier.DIM_HEIGHT);
        }
    }

    class ForegroundPanel extends JPanel {

        public ForegroundPanel() {
            setOpaque(false);
            setLayout(new FlowLayout(FlowLayout.TRAILING, 10, 0));
            JButton button = new JButton("I'm in the Foreground!");
            add(button);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(foregroundImage, 0, 0, DIM_WIDTH, DIM_HEIGHT, this);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(ThreeTier.DIM_WIDTH, ThreeTier.DIM_HEIGHT);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ThreeTier();
            }
        });
    }
}

更新

当然,您总是可以只使用JLayeredPane. 这就是它的用途。看这个例子

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class LayeredPaneDemo {

    public static final int DIM_WIDTH = 600;
    public static final int DIM_HEIGHT = 400;

    public LayeredPaneDemo() {
        ContainerPanel container = new ContainerPanel();
        JLabel title = new JLabel("Lame Google Map");
        title.setFont(new Font("verdana", Font.BOLD, 36));
        title.setHorizontalAlignment(JLabel.CENTER);
        JPanel panel = new JPanel(new GridBagLayout());
        panel.add(container);
        JFrame frame = new JFrame();
        frame.add(panel);
        frame.add(title, BorderLayout.NORTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new LayeredPaneDemo();
            }
        });
    }

    public class ContainerPanel extends JPanel {

        public ContainerPanel() {
            JLayeredPane layeredPane = new JLayeredPane();
            layeredPane.setPreferredSize(new Dimension(DIM_WIDTH, DIM_HEIGHT));
            BackgroundPanel bg = new BackgroundPanel();
            GroundPanel gg = new GroundPanel();
            ForegroundPanel fg = new ForegroundPanel();

            bg.setBounds(0, 0, DIM_WIDTH, DIM_HEIGHT);
            layeredPane.add(bg, new Integer(1));
            gg.setBounds(0, 0, DIM_WIDTH, DIM_HEIGHT);
            layeredPane.add(gg, new Integer(2));
            fg.setBounds(0, 0, DIM_WIDTH, DIM_HEIGHT);
            layeredPane.add(fg, new Integer(3));
            setLayout(new GridBagLayout());
            add(layeredPane);

            setBorder(new LineBorder(Color.BLUE, 10));
        }
    }

    public class ForegroundPanel extends JPanel {

        public ForegroundPanel() {
            JPanel buttonPanel = new JPanel(new GridLayout(3, 3));
            buttonPanel.setOpaque(false);
            buttonPanel.add(new JLabel());
            buttonPanel.add(new JButton("UP"));
            buttonPanel.add(new JLabel());
            buttonPanel.add(new JButton("Left"));
            buttonPanel.add(new JLabel());
            buttonPanel.add(new JButton("Right"));
            buttonPanel.add(new JLabel());
            buttonPanel.add(new JButton("Down"));
            buttonPanel.add(new JLabel());

            FlowLayout flow = (FlowLayout) getLayout();
            flow.setAlignment(FlowLayout.TRAILING);
            flow.setHgap(0);
            flow.setVgap(0);
            add(buttonPanel);
            setOpaque(false);

        }
    }

    public class GroundPanel extends JPanel {

        Image image = null;

        public GroundPanel() {

            try {
                image = ImageIO.read(getClass().getResource("/resources/california.png"));
            } catch (IOException ex) {
                Logger.getLogger(LayeredPaneDemo.class.getName()).log(Level.SEVERE, null, ex);
            }

            setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, DIM_WIDTH, DIM_HEIGHT, this);
        }
    }

    public class BackgroundPanel extends JPanel {

        public BackgroundPanel() {
            setLayout(new GridBagLayout());
            setBackground(Color.WHITE);
            try {
                Image img = ImageIO.read(getClass().getResource("/resources/google.jpg"));
                add(new JLabel(new ImageIcon(img)));
            } catch (IOException ex) {
                Logger.getLogger(LayeredPaneDemo.class.getName()).log(Level.SEVERE, null, ex);
            }


        }
    }
}
于 2014-04-01T04:10:36.520 回答