当前位置: 首页 > 知识库问答 >
问题:

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

勾炜
2023-03-14

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

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

从屏幕分辨率的85%开始
当我在代码中直接将大小设置为640x640时
在回答大小为640x540的JOptionPane时,网格已根据询问大小进行调整。但是,JLayeredPane并非如此

共有1个答案

陆昂然
2023-03-14

没有更多的上下文,就不可能知道你的代码出了什么问题。

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

有很多方法可以解决这个问题。就我个人而言,我会将网格和图像的渲染包装成一个组件,但这就是我。在这种情况下,您就不需要JLayeredPane了

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

那么,这里的问题就变成了保持两个组件的大小彼此同步。为此,我会使用 setPreferredSize 来动态更改大小。

“插入内部尖叫” - 任何时候我看到设置优先级大小它设置警钟。在这种情况下,我再次回退到使用单个组件,并提供一个与 getPreferredSize 配合使用的“大小调整”机制,但归根结底,这会将我们推向同一个方向。

为了将JLayeredPane布置在父容器的85%高度,同样,网格袋布局将是我的首选。

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

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

    }

}

所以,在你因为“与你的所作所为不符”而拒绝我之前,请理解:

  • 我没有关于你实际做了什么的背景,除了你的问题描述的概述
  • 我提供了一个可运行的示例,演示了您“可能”能够用来解决您的问题的基本概念,这比您为我们所做的更多
  • 这不是你可能实现这一目标的唯一方法,也绝不是我更喜欢的解决方案
 类似资料:
  • 问题内容: 我正在开发类似iGoogle的应用程序。使用iframe显示其他应用程序(在其他域上)的内容。 如何调整iframe的大小以适合iframe内容的高度? 我试图破译Google使用的javascript,但它被混淆了,到目前为止,在网络上搜索毫无结果。 更新: 请注意,内容是从其他域加载的,因此适用同源策略。 问题答案: 我们遇到了这类问题,但与您的情况略有不同我们向其他域上的网站提供

  • 问题内容: 在以Swift编写的iOS应用程序中使用自动布局时,如何根据内容调整textField的大小? 加载视图时以及用户键入时,文本字段将根据需要调整大小以适合其内容。 理想情况下,文本字段将在某个点(例如6行)处停止调整大小,并变为可滚动。 问题答案: 您必须使用而不是。 然后,您可以使用该方法。 但是首先,您必须知道一条线的高度。您可以使用以下方法获取该信息: 之后,只需在方法内部调用方

  • 问题内容: 它由9个框组成,中间带有文本。我已经制作了框,以便它们可以随着屏幕大小的变化而调整大小,以便始终保持在同一位置。 但是,即使我使用百分比,文本也不会调整大小。 如何调整文本的大小,使其在整个页面上始终具有相同的比例? 这是处理多种分辨率的合适解决方案吗?还是我应该在CSS中进行很多检查并为每种媒体类型设置许多布局? ``` html, body { } #launchmain { }

  • 请看下面的P5代码 这个小应用程序的目的是在画布上拖放图像,根据“上传”图像的宽度和高度改变其大小。 使用:成功加载图像(至少显示图像)后,我将其宽度和高度分配给变量和。接着是画布大小的变化。。。这会导致一个错误,画布的大小与上传的图像相同(在上选中),但不显示任何内容。 使用:当禁用上的画布大小更改并单击画布时,调整大小会完美地显示图像。 应用程序需要在不点击的情况下工作,在删除图像后应该自动更

  • 我正在使用 开发一个 Swing GUI。 有一个 ,其中包含两个 。后来我想在s中显示一些组件,我剪掉了这部分代码,使它更短。 如何将调整为的大小?不起作用,如果没有行设置首选大小,GUI将以最小大小显示。 编辑:我可以更改首选的大小行以适应最大的JPanel,但我提出这个问题是因为我希望< code>JFrame根据< code>JPanel的大小动态调整大小。