2015-05-12 9 views
12

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

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

1. Полный экран GUI

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

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

FullScreen GUI

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

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

Resized once GUI

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

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

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

Minimum size of the GUI

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

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

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

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


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

+1

Отличное объяснение поведения, которое вы ищете. Вы можете взломать что-то вместе с «ComponentListener», но, вероятно, это не очень хороший способ сделать это. Надеюсь, что кто-то, у кого больше опыта, чем я, увидит это и знает лучший способ. – Radiodef

ответ

7

Установка максимального/минимального/предпочтительного размера панели 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); 

      } 

     }); 
    } 
} 
+0

Большое спасибо за это, даже если я нахожу очень странным, чтобы положить голубую панель в зеленую панель класса, я буду использовать ее, чтобы сделать именно то, что я хочу! – Kapcash

2

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

Сначала установите для макета значение null.

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

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

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

+0

'Я не уверен, что это правильный способ:' - не использовать пустые макеты. Swing был разработан для использования с менеджерами компоновки. – camickr

3

Это должно быть легко с 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); 

Определяя вес х для голубого и синего компонента, а также установив размер = ГОРИЗОНТАЛЬНО они изменить размер контейнера.

2

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

+0

Большое спасибо за это, этот способ тоже полезен! – Kapcash

+0

@ Kapcash, не знаю, почему вам не нравится этот подход. Это чистый подход к макету, поэтому вы не пишете какой-либо код макета. Решение, которое вы приняли, в основном заново изобретает колесо, пытаясь вызвать собственный код макета с помощью ComponentListener. Мало того, что вам нужно создавать и управлять булевыми переменными, код макета встраивается во весь класс. – camickr

+0

Другой способ позволяет мне определять все, что мне нужно, не только для реальной проблемы, которую я имел. Убедитесь, что я тоже буду использовать ваше решение, но я ждал чего-то вроде компонентаListener, который может делать гораздо больше, чем один BoxLayout, который я уже знаю. Не разочаровывайтесь, я благодарю вас за это столько же, сколько «Копег». – Kapcash

0

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

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

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

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

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

+0

Спасибо, но мои вопросы были решены несколько месяцев назад. И это не касалось освежающей последовательности компонента, а только контрольной. – Kapcash

Смежные вопросы