Убедиться, что SpringLayout не сжимается ниже определенного размера - PullRequest
2 голосов
/ 04 января 2012

Я пытаюсь реализовать довольно простой пользовательский интерфейс, используя SpringLayout (отчасти потому, что я, в отличие от большинства авторов учебников, которые я нахожу в сети, довольно похож на интерфейс кодирования по сравнению с другими менеджерами компоновки, а отчасти потому, что я хочунаучиться им пользоваться).Пользовательский интерфейс в основном выглядит так:

UI template

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

UI when shrunk

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

Я знаю, что мог бы сделать это, обработав событие resize и проверив, достигнут ли минимальный размер, а затем просто установивРазмер до минимального размера.Но это требует от меня: а) знать или знать, как рассчитать минимальный размер окна, даже до того, как оно рендерится, б) написать кучу кода для обработки событий просто для того, чтобы получить правильную визуализацию пользовательского интерфейса, и в) написатькуча кода для вещей, которые, как я ожидаю, позаботится о хорошем менеджере компоновки;)

Ответы [ 2 ]

3 голосов
/ 04 января 2012
  1. вы можете переопределить MinimumSize для TopLevelContainer

  2. , который вы поставили JTextArea на JScrollPane

  3. Самый простой способ - это смешать LayoutManagers (называемый NestedLayout), разделив GUI на части (разделенные JPanels одинаковыми или разными LayoutManager), вместо того, чтобы реализовать самые сложные LayoutManager (GridBagLayout или SpringLayout) для всего Container

  4. некоторые LayoutManagers довольно игнорировать setXxxSize

  5. SpringLayout немоя чашка Java

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

public class MinSizeForContainer {

    private JFrame frame = new JFrame("some frame title");

    public MinSizeForContainer() {
        JTextArea textArea = new JTextArea(15, 30);
        JScrollPane scrollPane = new JScrollPane(textArea);

        CustomJPanel fatherPanel = new CustomJPanel();
        fatherPanel.setLayout(new SpringLayout());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(fatherPanel, BorderLayout.CENTER);
        frame.setLocation(20, 20);
        frame.setMinimumSize(fatherPanel.getMinimumSize());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MinSizeForContainer Mpgp = new MinSizeForContainer();
            }
        });
    }
}

class CustomJPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getMinimumSize() {
        return new Dimension(400, 400);
    }
}
2 голосов
/ 05 января 2012

Существует несколько проблем для достижения «реального» (который не может быть уменьшен) минимального размера:

  • дочерние компоненты должны возвращать минимальный (в зависимости от их содержимого) минимальный размер, многие основные компоненты не
  • layoutManager должен учитывать сложенный минимум всех дочерних элементов, независимо от того, насколько мало места доступно
  • контейнер верхнего уровня (здесь JFrame) не должен допускать усадку сверх минимума

Первое верно для JLabel, второе встречается для SpringLayout (поэтому ярлык усекается) - третья остается основной проблемой, решение которой неочевидно, на самом деле я не знал это даже возможно до запуска примера @ mKorbel. Соответствующая строка действительно

frame.setMinimumSize(someSize);

С этой линией невозможно уменьшить рамку ниже. Без, это так. Начиная с этого наблюдения, некоторое копание приводит к тому, что документ для переопределения в Window

Устанавливает минимальный размер этого окна в постоянное значение. [..] Если Размер текущего окна меньше минимального. Размер окна автоматически увеличивается до минимального размера. Если setSize или Методы setBounds впоследствии вызываются с шириной или высотой меньше [...] автоматически увеличивается, чтобы соответствовать значению минимального размера. Операция изменения размера может быть ограничена, если пользователь пытается изменить размер окно ниже значения минимального размера. Это поведение зависит от платформы.

Глядя на код, есть два (реализация, не полагайтесь на них :-) детали, относящиеся к минимальному размеру

 Dimension minSize;
 boolean minSizeSet;

и публичный API для доступа

 public Dimension getMinimumSize()
 public boolean isMininumSizeSet()

первый довольно старый (jdk1.1), последний довольно новый (jdk1.5) - это означает, что первый не может полагаться на последний, но внутренне должен проверить наличие нулевого minSize. Переопределенные методы определения размера (с их гарантией приложить все усилия для соблюдения установленного вручную minSize) в Window являются самыми последними (jdk6) и do полагаются на последнее. Или другими словами: переопределение isMinimumSizeSet ​​делает свое дело.

Некоторый фрагмент кода (будьте осторожны: это взломанный, непроверенный, вполне может зависеть от ОС с нежелательными побочными эффектами!):

    // JFrame.setDefaultLookAndFeelDecorated(true);
    JFrame frame = new JFrame("some frame title") {

        /**
         * Overridden to tricks sizing to respect the min.
         */
        @Override
        public boolean isMinimumSizeSet() {
            return true; //super.isMinimumSizeSet();
        }

        /**
         * Overridden to adjust for insets if tricksing and not using 
         * LAF decorations.
         */
        @Override
        public Dimension getMinimumSize() {
            Dimension dim = super.getMinimumSize();
            // adjust for insets if we are faking the isMinSet
            if (!super.isMinimumSizeSet() && !isDefaultLookAndFeelDecorated()) {
               Insets insets = getInsets();
               dim.width += insets.left + insets.right;
               dim.height += insets.bottom + insets.top;
            }
            return dim;
        }



    };
    // add a component which reports a content-related min
    JLabel label = new JLabel("Welcome to my application!");
    // make it a big min
    label.setFont(label.getFont().deriveFont(40f));
    frame.add(label); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
...