Изменение размера значка в кнопке до размера кнопок (+ с помощью LayoutManager) и увеличение шрифта до размера кнопок - PullRequest
0 голосов
/ 23 апреля 2019

В настоящее время я пытаюсь добавить значок, который должен быть размером с кнопку (добавлен к 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);
    }


    }

1 Ответ

0 голосов
/ 24 апреля 2019

Я пытался распечатать размер кнопки (после ее создания, а также после добавления). Это всегда дает мне 0 и, следовательно, ArgumentException (width (0) и height (0) должны быть ненулевыми).

да, это было бы по многим причинам

  • контейнер не проверен
  • , даже если подтверждено, их размер не является гарантией, пока его возвращаемое значение getTopLevelAncestor() не отображается! (ведь в этом случае ваш TestResize объект)
  • установка границы в null делает половину того, чтобы ваша кнопка достигла размера 0,0, так как первый надежный вызов для размера - это предпочтительный размер, и когда он не содержит содержимого и даже вставок (вставки границ) пользовательский интерфейс даст ему 0,0, так как он полностью пуст!

так что концепция была неправильной с самого начала, и даже если вы не сделали границу нулевой, размер будет равен вставкам границы (и для всех границ API, которые жесткие !!! даже для равнины " привет "с размером шрифта 5 !!!).

так что ваша лучшая ставка в такой ситуации (но не вашей, как я уже говорил) - это позвонить

back.getPreferredSize()

для того, чтобы это работало (в вашей ситуации), вы должны сделать начальный размер изображения самим, а затем при установке значка на кнопку пользовательский интерфейс придаст ему дополнительный размер.

Также я хочу динамически изменять размер шрифта до размера кнопки

@ Эндрю Томпсон указал на замечательные примеры в этом ответе, который он написал, и @trashgod хорошие примеры, все они потрясающие !! +1 за это.

<ч />

Редактировать

После этого спросите у кнопок его размер, а затем добавьте значок с таким же размером?

Вы должны понимать, что при использовании менеджеров компоновки каждый размер вещи относительно ее родителя !! для вашего примера кнопка со значком -> панель уровня (с панелью содержимого) -> корневая панель JLayeredPane объект -> корневая панель сама -> наконец, рамка !! размер каждой вещи изменяется в зависимости от родительского размера, но если в случае родительского размера 0,0, не ожидайте, что подкомпонент получит больше, чем это !! и просто помните, что GridBagLayout - самый сложный из всех макетов, и он может вести себя странным образом.

и использование

component.getWidth();
//and
component.getHeight();

- получить реальный размер «НА ЭКРАНЕ», возврат которого может быть даже не связан с 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);
    }

}

widthPadding и heightPadding - это общее количество вставок L & F для кнопок, я не могу вам помочь с этим, вы должны сделать это самостоятельно, это зависит от L & F. но для взлома вы можете изменить метод 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, это аккуратно и просто, и приятное кодирование.

...