【问题标题】:ImageIcon extends beyond window, resizing window expands all of components instead of showing moreImageIcon 超出窗口,调整窗口大小会扩展所有组件而不是显示更多
【发布时间】:2020-10-11 05:32:19
【问题描述】:
private void setupGUI(){
    // Setup Frame
    f = new JFrame("Shape Image Generator");
    f.setBounds(500, 150, 450, 350);
    f.setLayout(new GridLayout(8,1));
    f.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent windowEvent){
           System.exit(0);
        }
    });
}

我创建了上面的框架,然后创建了 8 个面板。我创建了各种组件并将它们添加到面板中,一切正常。直到我创建了一个 ImageIcon 并将其添加到标签并将该标签添加到第 8 个面板。使用的图像为 140x129 像素。问题是,只有顶部......可能显示了 1/4 的图像。如果我在代码中更改框架尺寸,则会在每个面板之间创建更多空白空间,但只显示更多的图像,因此图像仍然不在屏幕上。我会说窗口很容易为它显示的图像每增加 1 个像素添加 10 个像素的间距。如果我拖动窗口的角来展开它,也会发生同样的事情。如果窗口最大化,我仍然只能看到现在非常拉伸的图像的一半多一点。

我尝试过的事情:

  1. 我的组件都没有设置首选尺寸,但我尝试为标签设置首选尺寸,然后是包含 ImageIcon 的面板,它只在图像上方的灰色空间中添加了图像和首选尺寸之间的差异,进一步推动了它屏幕外。所以,我取消了那个。

  2. 将包含 ImageIcon 的标签添加到不是第 8 个也是最后一个面板的不同面板,在这种情况下,图像仍然被切断,但在它被切断时,它下面的面板上的组件出现(在切断图像的背景颜色之上)。

  3. 用大约 30 种不同的措辞方式对这种情况进行了详尽的谷歌搜索,但没有找到解决方案。

(row1 - row8 是 JPanel,我没有包含它们的编码)

    ImageIcon iconStart = createImageIcon("/images/ShapeClipart.png", "Shapes");
    JLabel imgLabel = new JLabel();
    row8.add(imgLabel);

    // Add image to image label
    imgLabel.setIcon(iconStart);

    // Add panels to frame
    f.add(row1);
    f.add(row2);
    f.add(row3);
    f.add(row4);
    f.add(row5);
    f.add(row6);
    f.add(row7);
    f.add(row8);

    f.setVisible(true);

Window at execution

Window when stretched

编辑: 添加 f.pack() 会产生一个非常高的瘦窗口(窗口高度比我的屏幕高)但是当我手动扩展窗口时它看起来仍然像(面板之间的空白,图像部分在屏幕外),即使我取出 f. setBounds 并且只使用 f.setLocation。

【问题讨论】:

  • 如果你打电话给f.pack(),那么你不应该打电话给f.setBounds()。此外,不要更改JFrame 布局,而是将所有“行”添加到单独的JPanel(带有GridLayout)并将该面板添加到JFrame。您是否有机会发布指向您正在使用的图标的链接?
  • 您尚未发布minimal reproducible example,因此我无法尝试重现您的问题。在任何情况下,不同的布局管理器可能更合适。也许BoxLayout?你见过Laying Out Components Within a Container吗?

标签: java user-interface imageicon


【解决方案1】:

您正在使用 GridLayout。这为所有封闭面板提供了相同数量的空间。在这种情况下,它是一个垂直网格。

您可能应该使用一些不同的东西。我可能会在 JFrame 中尝试 BorderLayout 并将包含前七个面板(在 GridLayout 中)的面板放入 CENTER,然后将 JLabel 放入 JFrame 的 SOUTH 部分。

还有其他的布局方式,但这是我能想到的第一个。

【讨论】:

  • 非常感谢!这行得通。我什至没有意识到可以为面板/多个布局管理器设置布局管理器。我使用了 setLocation 和 frame.pack() 而不是 setBounds,然后完全按照你说的做了,效果很好。
  • 要记住的重要一点是 LayoutManger 可以帮助开发人员,而不是妨碍他们。一旦您意识到您可以嵌套 LayoutManager 并专门使用它们来帮助您解决问题,它们就会更容易处理。您几乎不必调用 setBounds()。
【解决方案2】:

GridLayout使网格中的每个单元格大小相同,每个单元格的大小由网格中包含的最大Component决定。

在您的代码中,图标是最大的组件,并且您的网格中也只有一列,因此每一行都与您的图标具有相同的高度。

由于您还通过调用方法setBounds() 来限制JFrame 的大小,因此Swing 基础结构会切断图标,以便所有组件都适合您指定的范围。

一种替代方法,但不是唯一的一种方法是使用BoxLayout,因为它使用其包含的每个组件的首选大小。

这是一个与您发布的屏幕截图相匹配并使用BoxLayout 的示例 GUI。

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import java.net.URL;

import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

public class Shapes23 implements Runnable {
    private JFrame  frame;

    @Override // java.lang.Runnable
    public void run() {
        showGui();
    }

    private JPanel createEighthRow() {
        JPanel eighthRow = new JPanel();
        URL url = getClass().getResource("paint-bursht.jpg");
        Icon ico = new ImageIcon(url);
        JLabel label = new JLabel(ico);
        eighthRow.add(label);
        return eighthRow;
    }

    private JPanel createFifthRow() {
        JPanel fifthRow = new JPanel();
        JTextField textField = new JTextField(20);
        fifthRow.add(textField);
        return fifthRow;
    }

    private JPanel createFirstRow() {
        JPanel firstRow = new JPanel();
        JLabel label = new JLabel("2D Shapes");
        firstRow.add(label);
        return firstRow;
    }

    private JPanel createFourthRow() {
        JPanel fourthRow = new JPanel();
        fourthRow.add(createRadioButton("Sphere"));
        fourthRow.add(createRadioButton("Cube"));
        fourthRow.add(createRadioButton("Cone"));
        fourthRow.add(createRadioButton("Cylinder"));
        fourthRow.add(createRadioButton("Torus"));
        return fourthRow;
    }

    private JPanel createMainPanel() {
        JPanel mainPanel = new JPanel();
        BoxLayout layout = new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS);
        mainPanel.setLayout(layout);
        mainPanel.add(createFirstRow());
        mainPanel.add(createSecondRow());
        mainPanel.add(createThirdRow());
        mainPanel.add(createFourthRow());
        mainPanel.add(createFifthRow());
        mainPanel.add(createSixthRow());
        mainPanel.add(createSeventhRow());
        mainPanel.add(createEighthRow());
        return mainPanel;
    }

    private JRadioButton createRadioButton(String text) {
        JRadioButton radioButton = new JRadioButton(text);
        return radioButton;
    }

    private JPanel createSecondRow() {
        JPanel secondRow = new JPanel();
        secondRow.add(createRadioButton("Circle"));
        secondRow.add(createRadioButton("Rectangle"));
        secondRow.add(createRadioButton("Square"));
        secondRow.add(createRadioButton("Triangle"));
        return secondRow;
    }

    private JPanel createSeventhRow() {
        JPanel seventhRow = new JPanel();
        JButton button = new JButton("Enter");
        seventhRow.add(button);
        return seventhRow;
    }

    private JPanel createSixthRow() {
        JPanel sixthRow = new JPanel();
        JTextField textField = new JTextField(20);
        sixthRow.add(textField);
        return sixthRow;
    }

    private JPanel createThirdRow() {
        JPanel thirdRow = new JPanel();
        JLabel label = new JLabel("3D Shapes");
        thirdRow.add(label);
        return thirdRow;
    }

    private void showGui() {
        frame = new JFrame("Shape Image Generator");
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.add(createMainPanel(), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Shapes23());
    }
}

这是它外观的屏幕截图。请注意,我找不到与您的屏幕截图中相同的图标,所以我只使用了不同的图标。

【讨论】:

    猜你喜欢
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多