it-swarm.com.ru

Как динамически управлять компонентами автоматического изменения размера в Java Swing

Создание нового графического интерфейса в Java (1.8) Swing, я ищу способ переопределить поведение изменения размера всех моих компонентов.

Позвольте мне объяснить вам с некоторыми отредактированными фотографиями:

1. Полноэкранный графический интерфейс

Это мой полноэкранный графический интерфейс, с 3 панелями и JToolBar. Зеленый должен иметь фиксированный размер , остальные будут изменяемого размера .

В настоящее время у меня есть только 2 небольших GridLayout для их организации (одна вертикальная и одна горизонтальная для зеленой и голубой панелей).

FullScreen GUI

2. Небольшое горизонтальное изменение размера

Если я, например, уменьшу размер кадра с правой стороны, я хочу, чтобы моя сине-голубая панель была изменена в размере в соответствии с новым размером кадра. Но зеленая панель должна быть исправлена ​​. (Не самая сложная часть, я думаю.)

Resized once GUI

3. Минимальный горизонтальный размер

Это самая сложная часть для меня. Как только голубая (или синяя) панель достигнет минимального размера, я хочу, чтобы он " Нажмите " зеленую панель влево, даже если она исчезает с рамки.

Конечно, если потянуть рамку вправо, зеленая панель появится снова.

Minimum size of the GUI

Как я мог это сделать?

Я думал об использовании JSplitPane или определенного слушателя для ручного определения поведения изменения размера, но мне нужен совет.

Извините, если существующий пост может ответить на этот вопрос, я не нашел ответа, объясняющего проблему для меня.

Заранее спасибо!


Если вы хотите больше примеров, посмотрите на программное обеспечение "Evernote", которое работает так же

12
Kapcash

Задав максимальный/минимальный/предпочтительный размер панели Green, можно сохранить размер этой панели при первом условии. Чтобы проверить размеры, вы можете использовать ComponentListener на одном из JPanel - если размер становится меньше определенной ширины, измените максимальный/минимальный/предпочтительный размер панели Green

Ниже приведен пример взломанного вместе - он изменяет размер панели Green, когда Blue меньше 600, а изменение размера является взвешенным изменением размера (30% от общей ширины). Чтобы получить истинный L & F и то, что вы желаете, вам, возможно, придется поиграть с макетом/размерами. 

import Java.awt.BorderLayout;
import Java.awt.Color;
import Java.awt.Dimension;
import Java.awt.GridBagConstraints;
import Java.awt.GridBagLayout;
import Java.awt.GridLayout;
import Java.awt.Insets;
import Java.awt.Rectangle;
import Java.awt.event.ComponentAdapter;
import Java.awt.event.ComponentEvent;
import Java.awt.event.ComponentListener;

import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;


public class GridTest extends JPanel{

    private boolean changeAllowed = false;
    //keep reference to cyan for the height dimension
    final JPanel cyan = new JPanel();

    public GridTest(){
        cyan.setPreferredSize(new Dimension(600, 300));//provide sizing hint
    }

    private Dimension getCustomDimensions(){
        if ( changeAllowed ){
            return new Dimension((int)(super.getParent().getBounds().width * 0.3), cyan.getBounds().height);
        }else{
            return new Dimension(200, cyan.getBounds().height);
        }
    }
    @Override
    public Dimension getMaximumSize(){
        return getCustomDimensions();
    }
    @Override
    public Dimension getMinimumSize(){
        return getCustomDimensions();
    }
    @Override
    public Dimension getPreferredSize(){
        return getCustomDimensions();
    }

    public static void main(String[] args) throws Exception{
        SwingUtilities.invokeAndWait(new Runnable(){

            @Override
            public void run() {
                final int MINIMUM = 600;
                JFrame frame = new JFrame();
                frame.add(new JToolBar(), BorderLayout.NORTH);
                final JPanel blue = new JPanel();

                final GridTest green = new GridTest();
                green.setBackground(Color.green);
                green.setOpaque(true);

                green.cyan.setBackground(Color.cyan);
                green.cyan.setOpaque(true);
                blue.setOpaque(true);
                blue.setBackground(Color.blue);
                blue.setPreferredSize(new Dimension(900, 300));//hint at size
                blue.setMinimumSize(new Dimension(100, 200));//hint at size
                //Nest Box Layouts
                Box top = Box.createHorizontalBox();
                top.add(blue);
                Box bottom = Box.createHorizontalBox();
                bottom.add(green);
                bottom.add(green.cyan);
                Box vert = Box.createVerticalBox();
                vert.add(top);
                vert.add(bottom);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(vert);
                //listen for resizes
                blue.addComponentListener(new ComponentAdapter(){

                    @Override
                    public void componentResized(ComponentEvent e) {
                        if ( blue.getBounds().width < MINIMUM ){//set flag
                            green.changeAllowed = true;
                        }else{
                            green.changeAllowed = false;
                        }
                    }
                });

                frame.pack();
                frame.setSize(800, 600);
                frame.setVisible(true);

            }

        });
    }
}
7
copeg

Вот как я это делаю, и я не уверен, что это правильный путь:

Сначала установите макет на ноль.

Затем создайте событие с измененным размером компонента для вашего фрейма:

addComponentListener(new ComponentAdapter(){
            public void componentResized(ComponentEvent e){
            }
        });

Здесь вы можете вручную вносить изменения в компоненты по мере их изменения. Я сделал это для некоторых из моих программ, чтобы область прокрутки слева и справа от кадра всегда была одинаковой ширины, а размер остального размера увеличивался и уменьшался.

3
Forseth11

Это должно быть легко с GridBagLayout, при условии, что вы установите подходящие минимальные размеры для зеленого и голубого компонентов:

setLayout(new GridBagLayout());
green.setMnimumSize(new Dimension(0, 0));
cyan.setMinimumSize(new Dimension(100, 100)); // whatever fits
add(blue, new GridBagConstraints(0, 0, 2, 1,
        1.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
        new Insets(0, 0, 0, 0), 0, 0);
add(green, new GridBagConstraints(0, 1, 1, 1,
        0.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.NONE,
        new Insets(0, 0, 0, 0), 0, 0);
add(cyan, new GridBagConstraints(1, 1, 1, 1,
        1.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
        new Insets(0, 0, 0, 0), 0, 0);

Указывая вес x для голубого и синего компонентов, а также устанавливая resize = HORIZONTAL, они изменяют размер вместе с контейнером.

3
Durandal

Вы можете использовать BoxLayout, чтобы содержать зеленую и голубую панели. BoxLayout учитывает минимальный и максимальный размеры компонента. Таким образом, для зеленой панели вы устанавливаете максимальный размер, равный предпочтительному размеру, а для голубой панели вы устанавливаете минимальный размер, равный предпочтительному размеру:

import Java.awt.*;
import Java.util.*;
import javax.swing.*;

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        JPanel blue = new JPanel();
        blue.setBackground( Color.BLUE );
        blue.setPreferredSize( new Dimension(500, 100) );

        Box box = Box.createHorizontalBox();

        JPanel green = new JPanel();
        green.setBackground( Color.GREEN );
        green.setPreferredSize( new Dimension(200, 100) );
        green.setMaximumSize( green.getPreferredSize() );
        box.add( green );

        JPanel cyan = new JPanel();
        cyan.setBackground( Color.CYAN );
        cyan.setPreferredSize( new Dimension(300, 100) );
        cyan.setMinimumSize( cyan.getPreferredSize() );
        box.add( cyan );

        setLayout( new BorderLayout() );
        add(blue, BorderLayout.NORTH);
        add(box, BorderLayout.CENTER);
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

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

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

2
camickr

Важная последовательность такова:

                frame.revalidate();
                frame.pack();
                frame.repaint();
  1. revalidate (): делает недействительными компоненты до ближайшего корня, после чего компонент иерархия проверяется, начиная с ближайшего корневого элемента проверки.
  2. pack (): размер окна соответствует предпочтительному размеру и разметке его подкомпонентов. Результирующая ширина и высота окна автоматически увеличиваются.
  3. перекрасить (): После всех этих перерасчетов перекрашивание показывает компоненты.

Используйте эту последовательность после каждой серии изменений, которые вы сделали в своем коде, и хотите видеть результаты, появляющиеся на экране.

Мне нравится Java.awt.GridBagLayout в сочетании с Java.awt.GridBagConstraints , и я использую этот макет во всех контейнерах, запускающихся из области содержимого.

Если вы добавляете контейнер в другой контейнер, используйте макет для каждого из них, в противном случае вычисление не выполняется из-за отсутствия макета в иерархии.

0
michbau