2016-08-18 5 views
0

Я довольно новичок в Swing. У меня есть приложение, которое динамически генерирует пользовательский интерфейс на основе внешнего ввода. В верхней части панели есть JLabel с текстом заголовка, а затем кнопка (которая сообщает приложению перезагрузить динамически сгенерированный материал), а затем ниже, это JScrollPane, который содержит все динамически сгенерированные вещи. Я хочу, чтобы метка и кнопка занимали столько вертикального пространства, сколько им нужно, а затем панель прокрутки, чтобы заполнить все оставшееся свободное пространство.Как получить JScrollPane, чтобы заполнить все оставшееся свободное пространство

Я использую GridBagLayout и устанавливаю gbc.fill = BOTH, прежде чем добавить панель прокрутки.

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

Я нашел How to get a JScrollPane to resize with its parent JPanel, но это не работает, если JScrollPane не является единственным дочерним, так сказать.

Что я делаю неправильно?

SSCCE:

public class SwingTest { 
    public static void main(String[] args) { 
     JPanel bigPanel = new JPanel(); 
     bigPanel.setLayout(new GridLayout(10, 10)); 
     for (int i = 0; i < 100; i++) { 
      bigPanel.add(new JCheckBox("Item " + i)); 
     } 

     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.gridx = 0; 

     JFrame mainWindow = new JFrame("Swing Test"); 
     mainWindow.setLayout(new GridBagLayout()); 
     mainWindow.add(new JLabel("Heading"), gbc); 
     mainWindow.add(new JButton("Button"), gbc); 
     gbc.fill = GridBagConstraints.BOTH; 
     mainWindow.add(new JScrollPane(bigPanel), gbc); 

     mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     mainWindow.setLocationByPlatform(true); 
     mainWindow.pack(); 
     mainWindow.setVisible(true); 
    } 
} 

ответ

0

Таким образом, я понял это во время написания моего SSCCE. (Забавно, как это происходит!)

Основываясь на связанный с этим вопрос я связан, я попытался с помощью BorderLayout:

public class SwingTest { 
    public static void main(String[] args) { 
     JFrame mainWindow = new JFrame("Swing Test"); 

     mainWindow.setLayout(new BorderLayout()); 
     mainWindow.add(new JLabel("Heading")); 
     mainWindow.add(new JButton("Button")); 
     JPanel bigPanel = new JPanel(); 
     bigPanel.setLayout(new GridLayout(10, 10)); 
     for (int i = 0; i < 100; i++) { 
      bigPanel.add(new JCheckBox("Item " + i)); 
     } 
     mainWindow.add(new JScrollPane(bigPanel)); 

     mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     mainWindow.setLocationByPlatform(true); 
     mainWindow.pack(); 
     mainWindow.setVisible(true); 
    } 
} 

Но это не сработало, потому что я думаю, что я имел фундаментальное непонимание того, что делает BorderLayout , Не указывая ограничение на мои вызовы для добавления (...), я добавлял все три компонента в панель «ЦЕНТР». Цель BorderLayout состоит в том, чтобы разместить один компонент, который масштабируется с размером контейнера, и вы можете поместить другие вещи вокруг краев (то есть границы), которые останутся фиксированными. Только один компонент может находиться в каждой позиции, поэтому, добавив все три в CENTER, я остался только с последним, который я добавил. Мне нужно обернуть заголовок и кнопки в JPanel и положить, что на верхнем крае:

public class SwingTest { 
    public static void main(String[] args) { 
     JPanel top = new JPanel(); 
     top.setLayout(new BoxLayout(top, BoxLayout.PAGE_AXIS)); 
     top.add(new JLabel("Heading")); 
     top.add(new JButton("Button")); 

     JPanel bigPanel = new JPanel(new GridLayout(10, 10)); 
     for (int i = 0; i < 100; i++) { 
      bigPanel.add(new JCheckBox("Item " + i)); 
     } 

     JFrame mainWindow = new JFrame("Swing Test"); 
     mainWindow.setLayout(new BorderLayout()); 
     mainWindow.add(top, PAGE_START); 
     mainWindow.add(new JScrollPane(bigPanel), CENTER); 

     mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     mainWindow.setLocationByPlatform(true); 
     mainWindow.pack(); 
     mainWindow.setVisible(true); 
    } 
} 

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

public class SwingTest { 
    public static void main(String[] args) { 
     JPanel top = new JPanel(); 
     top.setLayout(new BoxLayout(top, BoxLayout.PAGE_AXIS)); 
     top.add(new JLabel("Heading")); 
     top.add(new JButton("Button")); 

     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.fill = NONE; 
     JPanel bigPanel = new JPanel(new GridBagLayout()); 
     for (int i = 0; i < 10; i++) { 
      gbc.gridx = RELATIVE; 
      gbc.gridy = i; 
      gbc.anchor = NORTHWEST; 
      for (int j = 0; j < 10; j++) { 
       bigPanel.add(new JCheckBox("Item " + (10 * i + j)), gbc); 
      } 
     } 

     // add a panel to the right side to prevent the grid from growing horizontally 
     gbc.fill = BOTH; 
     gbc.weightx = 1; 
     bigPanel.add(new JPanel(), gbc); 

     // add another panel to the bottom to prevent the grid from growing vertically 
     gbc.gridy = RELATIVE; 
     gbc.gridx = 0; 
     gbc.weightx = 0; 
     gbc.weighty = 1; 
     bigPanel.add(new JPanel(), gbc); 

     JFrame mainWindow = new JFrame("Swing Test"); 
     mainWindow.setLayout(new BorderLayout()); 
     mainWindow.add(top, PAGE_START); 
     mainWindow.add(new JScrollPane(bigPanel), CENTER); 

     mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     mainWindow.setLocationByPlatform(true); 
     mainWindow.pack(); 
     mainWindow.setVisible(true); 
    } 
} 

Takeaways:

  • Всегда подкладывайте JScrollPane сам по себе в центре BorderLayout.
  • Если вы не хотите, чтобы ваш сетчатый контент динамически расширял свою «ячейку» при изменении размера, используйте GridBagLayout, а не GridLayout.
+3

* «Итак, я понял это при написании моего SSCCE. (Забавно, как это происходит!)» * Хотя это может быть смешно, это также довольно часто. Это одно из (многих) преимуществ составления краткого примера. Это уменьшает большие, казалось бы сложные проблемы, вплоть до основных проблем, что, в свою очередь, облегчает просмотр проблем и решений. Рад, что вы его отсортировали.:) –

+3

Макет по умолчанию для области содержимого JFrame - это BorderLayout, поэтому нет необходимости в выражении 'mainWindow.setLayout (новый BorderLayout());' – FredK

+0

@AndrewThompson «Забавно, как это происходит!» должен был указать на это. Я обсуждал просто не публикацию, но мне потребовалось некоторое время, чтобы понять это, поэтому я решил не разрешать мне работать, а мой SSCCE пропадает. :) – JakeRobb

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