【问题标题】:How to make JLabel with image fill BorderLayout.CENTER如何使用图像填充 BorderLayout.CENTER 制作 JLabel
【发布时间】:2012-07-28 04:25:42
【问题描述】:

我有一个 JFrame 并将 LayoutManager 设置为 BorderLayout,然后继续添加我的 JLabel 和图像。但是,当我调整框架的大小时,JLabel 不会调整大小。我还没有在 North、S、E 等中添加任何组件。我希望简单地让标签内的图像填满整个框架,让我的菜单保持完整。

【问题讨论】:

  • 我希望有问题的图像足够大,占据空间。请看看这个example
  • 是的,图像足够大,不是小图标或任何东西。
  • 标签不会调整图标的大小 ;)

标签: java swing


【解决方案1】:

如果这看起来很自大,请原谅我,但我没有别的事情可做。

我做了一个快速的示例

看图片周围的红线,那是JLabel的边框。如您所见,标签已重新调整大小以填充整个区域。

这是我用来制作示例的代码

public class LayoutFrame extends JFrame {

    public LayoutFrame() throws HeadlessException {

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Image image = null;
        URL url = getClass().getResource("/layout/issue78.jpg");
        try {
            image = ImageIO.read(url);
        } catch (IOException ex) {

            ex.printStackTrace();

        }

        JLabel label = new JLabel(new ImageIcon(image));
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setVerticalAlignment(JLabel.CENTER);
        label.setBorder(new LineBorder(Color.RED, 4));

        setLayout(new BorderLayout());

        add(label);

    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                LayoutFrame frame = new LayoutFrame();
                frame.setSize(200, 200);
                frame.setLocationByPlatform(true);
                frame.setVisible(true);

            }
        });

    }

}

显然,您需要提供自己的图片;)。

不要忘记,标签不会为您缩放内容,如果这是您的目标,您需要实现自己的组件来实现这一目标。

如果您仍然遇到问题,我建议(在没有进一步证据的情况下)您的标签可能不在您认为的容器中,或者容器布局管理器不是您认为的那样。

更新

我不知道您为什么会遇到组件丢失或菜单问题的问题。是否混合了重量级和重量级的组件??

菜单栏示例

仔细阅读您的问题后,我设计了一个简单的调整图像窗格大小的示例。为了速度,我依赖于我的库,但用你自己的代码代替我的调用应该相当容易

public class ImagePane extends JPanel {

    protected static final Object RESIZE_LOCK = new Object();

    private BufferedImage image;
    private BufferedImage scaledImage;
    private Timer resizeTimer;

    public ImagePane() {

        URL url = getClass().getResource("/layout/issue78.jpg");
        try {
            image = ImageIO.read(url);
        } catch (IOException ex) {

            ex.printStackTrace();

        }

        resizeTimer = new Timer(250, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                // Simple thread factory to start a slightly lower 
                // priority thread.
                CoreThreadFactory.getUIInstance().execute(new ResizeTask());

            }

        });

        resizeTimer.setCoalesce(true);
        resizeTimer.setRepeats(false);

    }

    @Override
    public void setBounds(int x, int y, int width, int height) {

        super.setBounds(x, y, width, height);

        resizeTimer.restart();

    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        if (scaledImage != null) {

            // This simply returns a rectangle that takes into consideration
            //the containers insets
            Rectangle safeBounds = UIUtilities.getSafeBounds(this);

            System.out.println("scaledImage = " + scaledImage.getWidth() + "x" + scaledImage.getWidth());

            int x = ((safeBounds.width - scaledImage.getWidth()) / 2) + safeBounds.x;
            int y = ((safeBounds.height - scaledImage.getHeight()) / 2) + safeBounds.y;

            g2d.drawImage(scaledImage, x, y, this);

        }

    }

    protected class ResizeTask implements Runnable {

        @Override
        public void run() {

            synchronized (RESIZE_LOCK) {

                if (image != null) {

                    int width = getWidth();
                    int height = getHeight();

                    System.out.println("width = " + width);
                    System.out.println("height = " + height);

                    // A simple divide and conquer resize implementation
                    // this will scale the image so that it will fit within
                    // the supplied bounds
                    scaledImage = ImageUtilities.getScaledInstanceToFit(image, new Dimension(width, height), ImageUtilities.RenderQuality.High);

                    System.out.println("scaledImage = " + scaledImage.getWidth() + "x" + scaledImage.getWidth());

                    repaint(); // this is one of the few thread safe calls

                }

            }

        }

    }

}

【讨论】:

  • 感谢样品。它的问题是它接管了所有内容,而其他组件则丢失了,例如菜单。你是对的,我的问题是标签没有调整它里面的图标图像的大小是哪一部分的痛苦。
  • 它不应该影响你的菜单:P
  • @trashgod 不知道 OP 的知识水平,我不想听起来居高临下,但我不知道已经尝试过什么,所以我别无选择,只能从基础开始:P
【解决方案2】:

最好的选择是继承 ImageIcon 并覆盖它的 paintIcon 方法,以简单地使用 Graphics.paint(x, y, width, height ...) 绘制图像。

【讨论】:

  • 可以说是图标的非法实现:getIconWidth/Height 被记录为返回一个指定图标固定宽度的int——这不是可以动态调整大小...
  • 恕我直言,我认为您最好使用某种Factory,它可以采用基线Icon,并生成所需尺寸的新Icon,或者代表您绘制一个.但是,如果缩放操作相当大(例如缩小到 0.1% 或超过几个 100% - 取决于原始图像的大小),您将面临“停止”EDT 的风险。正如我的示例所示,它对调整大小请求使用“合并”方法,而不是在每个请求上调整大小,我们尝试在尽可能少的请求上调整大小,通常是在我们达到“空闲”状态时。但这只是 MHO
  • @madProgrammer 很抱歉原始 q 措辞不当,我不想调整图标内的图像大小。我只希望图像被拉伸以填充父组件。我知道这个糟糕的措辞可能会搞砸你的回复,但我希望它能解决我为什么尝试我所做的事情。
  • @mP 好的,那么拉伸不是调整大小吗?埃文你不关心保持纵横比吗
猜你喜欢
  • 2018-09-24
  • 2015-12-02
  • 2015-06-26
  • 2018-10-02
  • 1970-01-01
  • 2016-01-15
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多