如何创建具有 GridBagLayout 单元格精确尺寸的 ImageIcon

Posted

技术标签:

【中文标题】如何创建具有 GridBagLayout 单元格精确尺寸的 ImageIcon【英文标题】:How to create an ImageIcon with the exact dimensions of a GridBagLayout cell 【发布时间】:2021-10-05 10:32:41 【问题描述】:

对于我目前正在制作的简单 GUI,我想要一个类似的设计。

蓝色和绿色区域应该只是文本和数字。 红色区域应该是图像。目前,我正在创建图像的缩放实例,从中创建一个 ImageIcon,然后将其添加到标签以使图像适合不同的空间。 问题是,没有宽度我无法创建图片的缩放实例。

我当前的 GridBagLayout 代码如下所示:

private static void createAndShowUI()
    
        JFrame frame = new JFrame();
        JLabel map = new javax.swing.JLabel();
        JLabel data = new javax.swing.JLabel();
        JLabel menu = new javax.swing.JLabel();
        GridBagConstraints c;

        frame = new JFrame("Risiko");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);

        frame.getContentPane().setLayout(new GridBagLayout());

        map.setText("MAP");
        c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        c.weightx = 0.75;
        c.weighty = 0.75;
        frame.getContentPane().add(map, c);

        data.setText("DATA");
        c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 1;
        c.weighty = 0.25;
        frame.getContentPane().add(data, c);

        menu.setText("MENU");
        c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 0;
        c.gridheight = 2;
        c.weightx = 0.25;
        frame.getContentPane().add(menu, c);

        frame.setVisible(true);
    

我创建了三个区域,现在我想创建一个与红色区域的宽度和高度完全相同的图像。 所以我的问题是,如何获得红色区域的宽度和高度,以便创建图片的缩放实例,使其适合该区域?

【问题讨论】:

您可以尝试使用Stretch Icon。它将自动调整大小以填充可用空间。您需要“填充” GridBagConstraint 的属性以确保标签填充可用空间。或者另一种选择是创建一个 JPanel 并对图像进行自定义绘制。您可以使用 Graphics.drawImage(...) 方法来动态调整图像大小。 @camickr 好的,所以我想将您的方法与 Graphics.drawImage() 一起使用。我知道如何使用它以及它是如何工作的。现在的问题是 JPanel.getGraphics() 返回 null 因为它尚未初始化。我对摇摆相当陌生,以前从未使用过线程。我了解具有初始线程和事件调度线程的模型,但我不知道如何等到一切都初始化后再使用 JPanel 中的 Graphics.drawImage() 函数。你能帮我解决这个问题吗? “我不知道如何才能等到一切都初始化” 等到调用 repaint,然后在覆盖的 paintComponent(Graphics) 方法中绘制图像..永远不要在组件上调用getGraphics()。这不是自定义绘画的完成方式。 【参考方案1】:

通过调整框架大小来测试以下mre的动态布局。 用作MapPane 的背景的背景图像被调整大小以填充JPanels 的宽度和高度。 这是通过覆盖paintComponent来实现的:

import java.awt.*;
import java.awt.image.*;
import java.net.URL;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;

public class SwingTestPane extends JPanel 

    public SwingTestPane() 

          GridBagLayout gridBagLayout = new GridBagLayout();
          gridBagLayout.rowWeights = new double[]0.75, .25;
          gridBagLayout.columnWeights = new double[]0.75, 0.25;
          setLayout(gridBagLayout);

          GridBagConstraints c = new GridBagConstraints();
          c.fill = GridBagConstraints.BOTH;
          c.gridx = 0;
          c.gridy = 0;

          JPanel mapPane = new MapPane();
          add(mapPane, c);

          c.gridx = 0;
          c.gridy = 1;

          JLabel data = new javax.swing.JLabel("DATA");
          JPanel dataPane = new JPanel();
          dataPane.add(data);
          dataPane.setBackground(Color.YELLOW);
          dataPane.setOpaque(true);
          add(dataPane, c);

          c.gridx = 1;
          c.gridy = 0;
          c.gridheight = 2;

          JLabel menu = new JLabel("MENU");
          JPanel menuPane = new JPanel();
          menuPane.add(menu);
          menuPane.setBackground(Color.GREEN);
          menuPane.setOpaque(true);
          add(menuPane, c);
    

    @Override
    public Dimension getPreferredSize() 
        return new Dimension(400,400);
    
    public static void main(String[] args) 
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.getContentPane().add(new SwingTestPane());
        frame.pack();
        frame.setVisible(true);
    


class MapPane extends JPanel 

    String imageUrlString = "https://findicons.com/files/icons/345/summer/128/cake.png";
    BufferedImage image = null;
    MapPane() 
        URL url;
        try 
            url = new URL(imageUrlString);
            image = ImageIO.read(url);
         catch (IOException ex) 
            ex.printStackTrace();
        
    

    @Override //Override to paint image as the background
    protected void paintComponent(Graphics g) 
        super.paintComponent(g);
        g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    
 

【讨论】:

以上是关于如何创建具有 GridBagLayout 单元格精确尺寸的 ImageIcon的主要内容,如果未能解决你的问题,请参考以下文章

如何使组件跨越 GridBagLayout 中的多个单元格

如何使用 GridBagLayout 定位组件?

使用GridBagLayout控制行列的高度和宽度

GridBagLayout

GridBagLayout()的使用方法

GridBagLayout布局