根据用户的输入调整JLayeredPane的大小

时间:2018-02-09 19:27:20

标签: java swing

我正在开发一个精灵编辑器。我有一个扩展JPanel的类,在该类中,我使用JLayeredPane作为容器。在底层,有一个带有ImageIcon的JLabel,在顶层有一个JPanel,我绘制了一个网格。当代码运行时,我做了一些基本的数学运算,将JLayeredPane的首选大小设置为等于屏幕分辨率高度的85%左右。

我的问题是,当用户想要在其上绘制新画布时,我向JOptionPane询问用户所需画布的大小。然后我调用我的类构造函数来创建一个具有指定大小的新画布。之后,我在画布上应用revalidate()和repaint()方法。不幸的是,它不起作用。另外,当我试图获得画布的宽度和高度时,两者都给出0。但是,当我将自己的大小直接设置为代码时,它运行良好。因此,我想知道如何更新JLayeredPane的大小?

On start with a size of 85% of the screen resolution
When I set the size to 640x640 directly inside my code
When I answer the JOptionPane with a size of 640x640, the grid has been adapted to the asking size. However, it's not the case for the JLayeredPane

1 个答案:

答案 0 :(得分:1)

如果没有更多上下文,就无法知道代码出了什么问题。

但是,就个人而言,我将不再尝试重新发明轮子,并利用可用的布局管理API为您提供所需的支持。

您可以通过多种方式解决问题。我个人将网格和图像的渲染包装成单个组件,但那就是我。在这种情况下,您不需要JLayeredPane

让我们暂时假设JLayeredPane是不可协商的。然后我将布局管理器应用到JLayeredPane,这使得与其他两个组件(图像和网格)的交互更简单,因为布局管理器接管了控制权。因为你希望它们相互重叠,我很想使用GridBagLayout

这里的问题就是让两个组件的大小保持同步。为此,我使用setPreferredSize动态更改大小。

“插入内部尖叫” - 任何时候我看到setPreferredSize警报铃声。在这种情况下,我再次回到使用单个组件并提供与getPreferredSize一起使用的“大小调整”机制,但在一天结束时,这将使我们朝着同一方向前进。

为了在父容器的85%高度处布置JLayeredPane,再次GridBagLayout将是我的首选。

以下示例将JLayeredPane放置在想要填充父容器的可用空间(最多可用高度的85%)的位置。然后它允许图像和网格组件自动定位在该区域的一侧。

Default size Updated Size Change Size

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class Test {

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

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

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

    public class TestPane extends JPanel {

        private JLayeredPane lp;
        private ImagePane imagePane;
        private GridPane gridPane;

        public TestPane() throws IOException {
            setLayout(new GridBagLayout());

            lp = new JLayeredPane();
            lp.setLayout(new GridBagLayout());

            imagePane = new ImagePane();
            gridPane = new GridPane();

            gridPane.setForeground(new Color(255, 255, 255, 64));
            imagePane.setImg(ImageIO.read(...)));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;

            lp.add(imagePane, gbc);
            lp.add(gridPane, gbc);

            lp.setLayer(imagePane, 0);
            lp.setLayer(gridPane, 10);

            lp.setBackground(Color.RED);
            lp.setBorder(new LineBorder(Color.RED));

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

            add(lp, gbc);

            applyDesiredSize(200, 200);

            JButton btn = new JButton("Change");

            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.weighty = 0.25;
            add(btn, gbc);

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JTextField widthTF = new JTextField(4);
                    JTextField heightTF = new JTextField(4);

                    JPanel panel = new JPanel();
                    panel.add(new JLabel("Size: "));
                    panel.add(widthTF);
                    panel.add(new JLabel("x"));
                    panel.add(heightTF);

                    JOptionPane.showMessageDialog(TestPane.this, panel, "Change Size", JOptionPane.PLAIN_MESSAGE);

                    try {
                        int width = Integer.parseInt(widthTF.getText());
                        int height = Integer.parseInt(heightTF.getText());
                        applyDesiredSize(width, height);
                    } catch (NumberFormatException numberFormatException) {
                        JOptionPane.showMessageDialog(TestPane.this, "Invalid dimensions", "Error", JOptionPane.ERROR_MESSAGE);
                    }
                }
            });
        }

        protected void applyDesiredSize(int width, int height) {
            Dimension size = new Dimension(width, height);
//          lp.setPreferredSize(size);
            imagePane.setPreferredSize(size);
            gridPane.setPreferredSize(size);

            // Stop GridBagLayout from shrinking the components
            imagePane.setMinimumSize(size);
            gridPane.setMinimumSize(size);

            lp.revalidate();
            lp.repaint();
        }

    }

    public class ImagePane extends JPanel {

        private BufferedImage img;

        public ImagePane() {
        }

        public BufferedImage getImg() {
            return img;
        }

        public void setImg(BufferedImage img) {
            this.img = img;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(img, 0, 0, getWidth(), getHeight(), this);
            g2d.dispose();
        }

    }

    public class GridPane extends JPanel {

        private int gridSize = 10;

        public GridPane() {
            setOpaque(false);
        }

        public int getGridSize() {
            return gridSize;
        }

        public void setGridSize(int gridSize) {
            this.gridSize = gridSize;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(getForeground());
            for (int x = 0; x < getWidth(); x += gridSize) {
                g2d.drawLine(x, 0, x, getHeight());
            }
            for (int y = 0; y < getWidth(); y += gridSize) {
                g2d.drawLine(0, y, getWidth(), y);
            }
            g2d.dispose();
        }

    }

}

所以,在你向我射击之前因为它“与你所做的不相符”,请明白:

  • 我没有关于你实际做了什么的背景,除了你的问题描述的概述
  • 我提供了一个可运行的示例,演示了您“可能”可以用来解决问题的基本概念,这就是您为我们所做的更多
  • 这不是你实现这一目标的唯一方式,绝不是我的首选解决方案