【问题标题】:Resizing Icon in Button as big as Buttons size (+ using LayoutManager) and make Font as big as the Buttons size将 Button 中的图标大小调整为与 Buttons 一样大(+ 使用 LayoutManager)并使 Font 与 Buttons 一样大
【发布时间】:2021-12-02 20:55:12
【问题描述】:

目前我正在尝试添加一个应该与按钮一样大的图标(添加到GridBagLayout)。我想将图标缩放到按钮的大小,但我的按钮显示其大小为 0。

我尝试打印出按钮的大小(在创建按钮之后以及添加之后)。它总是给我0,因此ArgumentException(宽度(0)和高度(0)必须非零)。

我还想动态调整字体的大小,使其与按钮一样大(目前还没有实现,但也不起作用,因为按钮没有给出它的大小)。 有人有使用LayoutManager 动态调整大小的解决方案吗?也许有一种方法可以获取单元格大小,然后将图像缩放到单元格大小?

这是我的测试代码:


    import javax.swing.*;
    import java.awt.*;


    public class TestResize extends JFrame {

    private Container cp;
    private JPanel levelPane;
    private GridBagConstraints gbc = new GridBagConstraints();


    public TestResize() {
        super();
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        int frameWidth = 200;
        int frameHeight = 200;
        setSize(frameWidth, frameHeight);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        setTitle("temp");
        setResizable(false);
        cp = getContentPane();
        cp.setLayout(new BorderLayout());

        createLevelMenu();


        setVisible(true);
    } // end of public temp


    public static void main(String[] args) {
        new TestResize();
    } // end of main

    public void createLevelMenu(){

        if (levelPane == null){
            levelPane = new JPanel(new GridBagLayout());

            gbc.fill = GridBagConstraints.NONE;

            JButton back = new JButton();
            back.setOpaque(false);
            back.setBackground(null);
            back.setBorder(null);

            addObject(0,0,1,1,GridBagConstraints.FIRST_LINE_START,back);
            Image img = (new ImageIcon("Content/Graphics/UI/returnIcon.png")).getImage().getScaledInstance(back.getWidth(),back.getHeight(),Image.SCALE_SMOOTH);
            back.setIcon(new ImageIcon(img));

            JPanel menu = new JPanel(new BorderLayout());
            menu.setBackground(Color.RED);
            JLabel l = new JLabel("Demo");
            l.setFont(l.getFont().deriveFont(30)); //Font Size as big as Possible (adjust
            l.setHorizontalAlignment(SwingConstants.CENTER);
            l.setVerticalAlignment(SwingConstants.CENTER);
            menu.add(l,BorderLayout.CENTER);
            gbc.fill = GridBagConstraints.BOTH;
            addObject(2,2,1,4,GridBagConstraints.CENTER,menu);

            JButton info = new JButton("Info");
            addObject(3,3,1.25f,1.25f,GridBagConstraints.LAST_LINE_END,info);

            cp.add(levelPane, BorderLayout.CENTER);
        }
    }

    public void addObject(int gridX,int gridY, double weightX,double weightY,int anchor, JComponent comp){
        gbc.gridx =gridX;
        gbc.gridy = gridY;
        gbc.weightx = weightX;
        gbc.weighty = weightY;
        gbc.anchor = anchor;
        levelPane.add(comp,gbc);
    }


    }

【问题讨论】:

标签: java swing layout-manager image-resizing gridbaglayout


【解决方案1】:

我尝试打印出按钮的大小(在创建按钮之后以及添加之后)。它总是给我 0,因此 ArgumentException(宽度 (0) 和高度 (0) 必须非零)。

是的,这有很多原因

  • 容器未验证
  • 即使验证了它们也不能保证大小,只要它返回的getTopLevelAncestor() 是不可显示的! (在这种情况下是你的 TestResize 对象)
  • 将边框设置为 null 使按钮大小变为 0,0 的方式只有一半,因为对大小的第一个可靠调用是首选大小,并且当它不包含内容且甚至没有内嵌时(边框内嵌)用户界面将给它 0,0,因为它完全是空的!

所以这个概念从一开始就是错误的,即使你没有将边框设置为 null,大小也将等于边框插图(对于所有 api 边框都是紧的!!!即使是普通的“ hi”,字体大小为 5 !!!)。

所以在这种情况下你最好的选择(但不是我提到的你的)是跟注

back.getPreferredSize()

为此(在您的情况下),您必须自己设置图像的起始大小,然后在将图标设置为按钮时,用户界面会给它一个额外的大小。

我还想动态调整字体大小与按钮一样大

@AndrewThompson 在他写的那个答案中指出了一个很好的例子,@trashgod 很好的例子也都很棒!为此 +1。


编辑

然后询问按钮的大小,然后添加相同大小的图标?

你必须明白,当使用布局管理器时,每个东西的大小都是相对于它的父级的!! 对于你的例子 图标按钮 --> 关卡面板(它是内容面板) --> 根面板 JLayeredPane 对象 --> 根面板本身 --> 最后是框架! 每件事都会根据父大小调整大小,但如果父大小为 0,0,那么不要指望子组件会得到更多! 请记住,GridBagLayout 是所有布局中最复杂的,它的行为方式可能很奇怪。

以及

的用法
component.getWidth();
//and
component.getHeight();

是为了获得真正的尺寸'ON-THE-SCREEN',回报可能甚至与getSize()或其他(最大,最小)无关。

所以最好的方法是让图标的大小与你必须制作的大小相同 ComponentListener

相同大小的图标

这是一个坏主意,因为如果 L & F 有一个默认的按钮插图,那么你会给它比它需要的更多! 并使用ComponentListener,您将使其具有调整大小的动画!

这里是你的类的重构版本, ComponentAdapter 是接口ComponentListener 的一个实现,它以空的方式实现每个方法,我正在使用它,所以我也不必实现所有其他方法。


import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import mdlaf.utils.MaterialImages;

public class TestResize extends JFrame {

    private Container cp;
    private JPanel levelPane;
    private GridBagConstraints gbc = new GridBagConstraints();

    public TestResize() {
        super();
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        int frameWidth = 200;
        int frameHeight = 200;
        setSize(frameWidth, frameHeight);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        setTitle("temp");
        setResizable(false);
        cp = getContentPane();
        cp.setLayout(new BorderLayout());
        createLevelMenu();
        GridBagLayout gbl = (GridBagLayout) levelPane.getLayout();
        gbc = gbl.getConstraints(back);
        gbc.fill = GridBagConstraints.BOTH;
        levelPane.remove(back);
        levelPane.add(back, gbc);
        back.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                //here you can add an image relative to the new size !!
                if (back.getIcon() == null) {
                    fixIcon();
                } else if (back.getIcon().getIconHeight() != back.getHeight() - heightPadding || back.getIcon().getIconWidth() != back.getWidth() - widthPadding) {

                    fixIcon();
                }
            }

        });
        setVisible(true);
    } // end of public temp

    private int widthPadding;
    private int heightPadding;

    private void fixIcon() {
        Image img = (new ImageIcon(MaterialImages.BACK_ARROW)).getImage().getScaledInstance(back.getWidth() - widthPadding, back.getHeight() - heightPadding, Image.SCALE_SMOOTH);
        back.setIcon(new ImageIcon(img));
    }

    public static void main(String[] args) {
        new TestResize();
    } // end of main
    JButton back;

    public void createLevelMenu() {

        if (levelPane == null) {
            levelPane = new JPanel(new GridBagLayout());

            gbc.fill = GridBagConstraints.NONE;

            back = new JButton();
            back.setOpaque(false);
            back.setBackground(null);
            back.setBorder(null);
            addObject(0, 0, 1, 1, GridBagConstraints.FIRST_LINE_START, back);
            JPanel menu = new JPanel(new BorderLayout());
            menu.setBackground(Color.RED);
            JLabel l = new JLabel("Demo");
            l.setFont(l.getFont().deriveFont(30)); //Font Size as big as Possible (adjust
            l.setHorizontalAlignment(SwingConstants.CENTER);
            l.setVerticalAlignment(SwingConstants.CENTER);
            menu.add(l, BorderLayout.CENTER);
            gbc.fill = GridBagConstraints.BOTH;
            addObject(2, 2, 1, 4, GridBagConstraints.CENTER, menu);

            JButton info = new JButton("Info");
            addObject(3, 3, 1.25f, 1.25f, GridBagConstraints.LAST_LINE_END, info);

            cp.add(levelPane, BorderLayout.CENTER);
        }
    }

    public void addObject(int gridX, int gridY, double weightX, double weightY, int anchor, JComponent comp) {
        gbc.gridx = gridX;
        gbc.gridy = gridY;
        gbc.weightx = weightX;
        gbc.weighty = weightY;
        gbc.anchor = anchor;
        levelPane.add(comp, gbc);
    }

}

widthPaddingheightPadding 是按钮的 L & F 插图的总和,我无法帮助你,你必须自己做,这是一个 L & F 依赖。 但是对于 hack,您可以将 componentResized 方法更改为此(我不鼓励这样做)

public void componentResized(ComponentEvent e) {
                //here you can add an image relative to the new size !!
                if (back.getIcon() == null) {
                    back.removeComponentListener(this);
                    fixIcon();
                }

我已经看过这个例子,但我觉得它有点复杂,所以我认为可能有更好(更简单)的解决方案。

遗憾的是,我不这么认为,但@AndrewThompson 的答案似乎很容易学习,如果我想开始阅读有关 GlyphVector 的内容,我会研究它很简洁,而且编码很简单。

【讨论】:

  • 首先感谢您的评论。 @AndrewThompson 感谢这篇文章,我已经看过这个例子,但我觉得它有点复杂,所以我认为可能有更好(更简单)的解决方案。还是谢谢。
  • 问题是我使用了一个 LayoutManager(在这个例子中是 GridBagLayout)。我不想使用任何绝对值,因此是否可以使 Button 与 LayoutManager(我的网格)允许的一样大。之后询问按钮的大小,然后添加相同大小的图标?
  • 我也忘了提
  • `` 是否有可能使 Button 与 LayoutManager(我的网格)允许的一样大``有点棘手!按钮位置是 (0,0),在 0 行或 0 列没有其他配合,GBL 根据列上的最大宽度和行上的最大高度计算最大宽度和高度,所以在这个如果按钮大小被认为是每个中的最大值! ,并且如果您覆盖了按钮的paintComponentgetPreferredSize,则可以使按钮的大小与图标的大小相同。@KevinKumar
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-26
  • 2023-03-06
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多