2017-02-05 11 views
0

Я выполнил поиск StackOverflow, но все вопросы, похоже, задают полную противоположность моей проблеме.Swing - компоненты GridLayout не заполняют все свободное пространство

Я пишу код, который динамически добавляет JLabels в JPanel с GridLayout, все они содержатся в пределах JScrollPane. Вот SSCCE:

private JFrame frame; 
private JPanel panel; 
static Test window; 
private JScrollPane scrollPane; 

public static void main(final String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       window = new Test(); 
       window.frame.setVisible(true); 
      } catch (final Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 

    for (int i = 0; i < 100; i++) { 
     try { 
      EventQueue.invokeAndWait (new Runnable() { 
       @Override 
       public void run() { 
        final JLabel label = new JLabel("Test"); 
        label.setSize(160, 40); 
        label.setHorizontalAlignment(SwingConstants.CENTER); 
        // Finalise GUI 
        window.panel.add(label); 
        window.panel.revalidate(); 
        window.panel.repaint(); 
        try { 
         Thread.sleep(100); 
        } catch (final Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      }); 
     } catch (final Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

public Test() { 
    initialize(); 
} 

private void initialize() { 
    frame = new JFrame(); 
    frame.setBounds(100, 100, 500, 200); 
    frame.getContentPane().setLayout(null); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    panel = new JPanel(); 
    panel.setLayout(new GridLayout(0, 3)); 

    final JPanel outerPanel = new JPanel(); 
    outerPanel.setLayout(new FlowLayout()); 
    outerPanel.add(panel); 

    scrollPane = new JScrollPane(outerPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
    scrollPane.setBounds(12, 0, 460, 160); 
    frame.getContentPane().add(scrollPane); 
} 

В моем понимании, в GridLayouts, «каждый компонент занимает все доступное пространство в пределах своей ячейки.» Однако здесь JLabels фактически не занимают все свободное пространство в JPanel.

Я не уверен, где моя ошибка. Это в GridLayout или в окружении Components, не давая GridLayout достаточно места?

Спасибо всем.

+0

Что вы здесь делаете? Особенно с этим 'Thread.sleep (100);' вызван потоком событий Swing ?? –

+0

См. Правки для ответа –

+0

'Thread.sleep (100);' был там, поэтому я мог видеть, что JLabels добавляются один за другим, сохраняя код коротким. – Glenn

ответ

3

Ваши JLabels : Принимаются все возможные пространства. Это твой JPanel маленький. Проверьте это самостоятельно с каймой:

panel = new JPanel(); 
    panel.setLayout(new GridLayout(0, 3)); 

    // **** add this to see **** 
    panel.setBorder(BorderFactory.createLineBorder(Color.BLUE)); 

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

final JPanel outerPanel = new JPanel(); 
    // !! outerPanel.setLayout(new FlowLayout()); 
    outerPanel.setLayout(new BorderLayout()); // !! 
    // !! outerPanel.add(panel); 
    outerPanel.add(panel, BorderLayout.PAGE_START); // !! 

Кроме того, что Thread.sleep(...) опасен код в GUI Swing. Если вы хотите задержать добавление компонентов, используйте лучший инструмент Swing для задания: a Swing Timer. Например

final int timerDelay = 100; 
    final int maxLabelCount = 100; 
    new Timer(timerDelay, new ActionListener() { 
     private int labelCount = 0; 
     @Override 
     public void actionPerformed(ActionEvent evt) { 
      if (labelCount < maxLabelCount) { 
       final JLabel label = new JLabel("Test"); 
       // !! label.setSize(160, 40); // NO! 
       label.setHorizontalAlignment(SwingConstants.CENTER); 
       // Finalise GUI 
       window.panel.add(label); 
       window.panel.revalidate(); 
       window.panel.repaint(); 
      } else { 
       // stop this timer 
       ((Timer) evt.getSource()).stop(); 
      } 
      labelCount++; 
     } 
    }).start();