Swing JLayeredPane不会在paintAll调用上绘制所有元素

时间:2015-12-16 08:00:15

标签: java swing canvas awt jlayeredpane

我的JLayeredPane在级别0上包含Canvas(在Paint方法中填充黄色),在级别1上包含JPanel(在背景中设置为paintAllToImage在构造函数中为红色)。

点击按钮点击BufferedImage方法我创建JLayerePane并使用component.paintAll(image.getGraphics());在此图片上绘制Canvas。问题是,该图片只有{{ 1}}画(它完全填充黄色)。请参阅附图。

enter image description here

(按钮上方的部分是实际绘制的,按钮下方的部分是图像,由JLayeredPane创建)

以下是完整代码:

public class LayeredPaneEx extends JPanel {

    private JLayeredPane layeredPane;
    public LayeredPaneEx()    {
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

        layeredPane = new JLayeredPane();
        layeredPane.setPreferredSize(new Dimension(300, 310));
        layeredPane.setLayout(null);

        Canvas panel = new CustomCanvas();
        panel.setSize(300, 400);
        CustomPanel customPanel = new CustomPanel();
        layeredPane.add(panel, new Integer(0));
        layeredPane.add(customPanel, new Integer(1));

        add(layeredPane);

        JButton paintBtn = new JButton("Paint All");
        paintBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ImageIcon icon = new ImageIcon(paintAllToImage(layeredPane));
                JLabel imageLabel = new JLabel(icon);
                add(imageLabel);
            }
        });
        add(paintBtn);

        JLabel paintLabel = new JLabel();
        paintLabel.setPreferredSize(new Dimension(300, 300));
    }

    private class CustomCanvas extends Canvas  {
        @Override
        public void paint(Graphics g) {
            g.setColor(Color.YELLOW);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }

    private class CustomPanel extends JPanel {
        CustomPanel() {
            setSize(100, 100);
            setBackground(Color.RED);
        }
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("LayeredPaneDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JComponent newContentPane = new LayeredPaneEx();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

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

    public static BufferedImage paintAllToImage(Component component) {
        BufferedImage image;
        image = new BufferedImage(
                component.getWidth(),
                component.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );
        component.paintAll(image.getGraphics());
        return image;
    }
}

1 个答案:

答案 0 :(得分:2)

编辑:新答案

通过调整此Stack Overflow answer,似乎可以将轻量级CustomPanel置于重量级Panel中,并将其放在另一个重量级Panel之上。这是一个截图:

Screenshot showing lightweight on top of heavyweight

以下是该计划:

import java.awt.*;
import javax.swing.*;

/**
 * Adapted from https://stackoverflow.com/a/1428298/1694043.
 */
public class GuiTest {
    public static void main(String[] arguments) {
        new GuiTest();
    }

    public GuiTest() {
        JFrame frame = new JFrame("Heavyweight versus lightweight");
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        addPanelsToFrame(frame);

        SwingUtilities.invokeLater(() -> frame.setVisible(true));
    }

    private void addPanelsToFrame(JFrame frame) {
        CustomCanvas customCanvas = new CustomCanvas(300, 400, Color.YELLOW);
        Panel awtPanel1 = new Panel(new BorderLayout());
        awtPanel1.setSize(300, 400);
        awtPanel1.add(customCanvas, BorderLayout.CENTER);
        frame.getLayeredPane().add(awtPanel1, JLayeredPane.DEFAULT_LAYER);

        CustomPanel customPanel = new CustomPanel(100, 100, Color.RED);
        Panel awtPanel2 = new Panel(new BorderLayout());
        awtPanel2.setSize(100, 100);
        awtPanel2.add(customPanel, BorderLayout.CENTER);
        frame.getLayeredPane().add(awtPanel2, JLayeredPane.PALETTE_LAYER);
    }


    private class CustomCanvas extends Canvas {
        private Color backgroundColor;

        public CustomCanvas(int width, int height, Color backgroundColor) {
            setSize(width, height);
            this.backgroundColor = backgroundColor;
        }

        @Override
        public void paint(Graphics g) {
            g.setColor(backgroundColor);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    }


    private class CustomPanel extends JPanel {
        public CustomPanel(int width, int height, Color backgroundColor) {
            setSize(width, height);
            setBackground(backgroundColor);
        }
    }
}

旧答案

使用MadProgrammer的建议来避免Canvas类,您可以使用CustomPanel类的两个实例。此类扩展了基于Swing的轻量级JPanel,而不是基于Canvas的重量级AWT。有关轻量级和重量级Java GUI组件的更多信息,请参阅https://stackoverflow.com/a/13769255/1694043

以下是截图:

Screenshot of modified program

以下是修改后的代码:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;

public class LayeredPaneEx extends JPanel {
    private JLayeredPane layeredPane;

    public LayeredPaneEx()    {
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

        layeredPane = new JLayeredPane();
        layeredPane.setPreferredSize(new Dimension(300, 310));
        layeredPane.setLayout(null);

        //Canvas panel = new CustomCanvas();
        //panel.setSize(300, 400);
        //CustomPanel customPanel = new CustomPanel();
        //layeredPane.add(panel, new Integer(0));
        //layeredPane.add(customPanel, new Integer(1));
        layeredPane.add(new CustomPanel(300, 400, Color.YELLOW), new Integer(0));
        layeredPane.add(new CustomPanel(100, 100, Color.RED), new Integer(1));

        add(layeredPane);

        JButton paintBtn = new JButton("Paint All");
        paintBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ImageIcon icon = new ImageIcon(paintAllToImage(layeredPane));
                JLabel imageLabel = new JLabel(icon);
                add(imageLabel);
            }
        });
        add(paintBtn);

        JLabel paintLabel = new JLabel();
        paintLabel.setPreferredSize(new Dimension(300, 300));
    }

//    private class CustomCanvas extends Canvas  {
//        @Override
//        public void paint(Graphics g) {
//            g.setColor(Color.YELLOW);
//            g.fillRect(0, 0, getWidth(), getHeight());
//        }
//    }

    private class CustomPanel extends JPanel {
        public CustomPanel(int width, int height, Color backgroundColor) {
            setSize(width, height);
            setBackground(backgroundColor);
        }
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("LayeredPaneDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JComponent newContentPane = new LayeredPaneEx();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

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

    public BufferedImage paintAllToImage(Component component) {
        BufferedImage image = new BufferedImage(
                component.getWidth(),
                component.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );
        component.paintAll(image.getGraphics());

        return image;
    }
}