2015-05-20 7 views
3

Ниже приведен пример добавления двух панелей в рамку. Отображается только одна панель (вторая, красная панель).Почему первая панель, добавленная к кадру, исчезает?

Disappearing Panel In Frame

Почему первая панель исчезнет?

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

public class DisappearingPanelInFrame { 

    DisappearingPanelInFrame() { 
     JFrame f = new JFrame(this.getClass().getSimpleName()); 
     f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     f.add(new ColoredPanel(Color.GREEN)); 
     f.add(new ColoredPanel(Color.RED)); 

     f.pack(); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     Runnable r = new Runnable() { 
      @Override 
      public void run() { 
       new DisappearingPanelInFrame(); 
      } 
     }; 
     SwingUtilities.invokeLater(r); 
    } 
} 

class ColoredPanel extends JPanel { 

    ColoredPanel(Color color) { 
     setBackground(color); 
     setBorder(new EmptyBorder(20, 150, 20, 150)); 
    } 
} 
+1

Определенно [автоответчик-FAQ] (http://meta.stackoverflow.com/q/17463/163188); для использования «границы» для получения определенного начального размера; поскольку вы расширяете 'JPanel', также учитывайте переопределение [' getPreferredSize() '] (http://stackoverflow.com/q/7229226/230513). – trashgod

+1

@trashgod Да. Я решил переопределить 'getPreferredSize()' вместо того, чтобы устанавливать границу (я также считал, что просто устанавливаю размер для самого кадра!). Я был между двумя разными подходами. 1) Используйте лучшие практики во всех отношениях. 2) Сделайте весь образец кода в едином блоке кода без вертикальной полосы прокрутки. - В этом случае последний выиграл (в основном). ;) –

ответ

5
  • макет по умолчанию в JFrame (или более конкретно, в этом случае, панель содержание кадра) является BorderLayout.
  • При добавлении компонента в BordeLayout без ограничений, Swing API поместит компонент в CENTER.
  • A BorderLayout может содержать точно один компонент в каждом из 5 ограничений макета.
  • Когда второй компонент добавляется к тому же (в данном случае CENTER), ограничение BorderLayout, эта реализация Java отобразит последний добавленный компонент .

Что касается лучшего подхода, зависит от конкретных потребностей пользовательского интерфейса.

+0

Этот ответ будет принят через два дня (скорее всего). Другие качественные ответы могут привлечь щедрость. –

+1

Я только понял, что вы, вероятно, уже знали ответ, хе-хе. – immibis

+0

@immibis Да. :) Я бы в значительной степени написал этот ответ дважды в качестве комментария за последние 24 часа, и это заставило меня подумать, что стоило создавать вопросы и ответы, которые можно было бы использовать в качестве дубликата. ;) –

3

Когда второй компонент добавлен к тому же (в данном случае CENTER) ограничению BorderLayout, эта реализация Java покажет последний добавленный компонент.

Не совсем верно.

BorderLayout будет только reset the bounds (т.е. размер и местоположение) последнего компонента, добавленного в определенное место ограничения. Это отличается от других менеджеров компоновки тем, что они сбросят границы всех компонентов в контейнере.

В примере кода красная панель была «активной» панелью во время проверки кадра с использованием метода pack(), и поэтому была установлена ​​только его граница, и поэтому только она была нарисована.

Для демонстрации этого процесса запустить пример ниже, используя следующие шаги:

  1. Нажмите на кнопку «Добавить панель в Центре», ничего не кажется произойдет, даже если синяя панель была добавлена ​​в центре ,
  2. Наведите указатель мыши на красную панель, и появятся кнопки, потому что логика опрокидывания мыши приведет к перекрашиванию кнопок.
  3. Теперь увеличьте ширину рамки, и синяя панель появится под красной панелью.

Код:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 

public class DisappearingPanelInFrame { 

    DisappearingPanelInFrame() 
    { 

     JButton button = new JButton ("Add Panel In Center"); 
     button.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       JPanel blue = new JPanel(); 
       blue.setBackground(Color.BLUE); 
       blue.add(new JButton("Button 1")); 
       blue.add(new JButton("Button 2")); 

       Component c = (Component)e.getSource(); 
       Window window = SwingUtilities.windowForComponent(c); 
       window.add(blue); 
       window.revalidate(); 
       window.repaint(); 
      } 
     }); 

     JFrame f = new JFrame(this.getClass().getSimpleName()); 
     f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     f.add(new ColoredPanel(Color.GREEN)); 
     //f.pack(); 
     f.add(new ColoredPanel(Color.RED)); 
     f.add(button, BorderLayout.SOUTH); 

     f.pack(); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     Runnable r = new Runnable() { 
      @Override 
      public void run() { 
       new DisappearingPanelInFrame(); 
      } 
     }; 
     SwingUtilities.invokeLater(r); 
    } 
} 

class ColoredPanel extends JPanel { 

    ColoredPanel(Color color) { 
     setBackground(color); 
     setBorder(new EmptyBorder(20, 150, 20, 150)); 
    } 
} 

Когда синяя панель добавляется к BorderLayout и когда revalidate() вызываются за пределы синих панелей установлена.

Однако из-за того, что Swing рисует ZOrder, сначала рисуется синяя панель, а затем красная панель окрашивается поверх синей панели. Зеленая панель по-прежнему имеет размер (0, 0), поскольку она никогда не была «активной» панелью в BorderLayout.CENTER, когда кадр был первоначально проверен с помощью метода pack().

При изменении размера рамки синяя панель, являющаяся «активной» панелью в BorderLayout.CENTER, имеет свои границы, поэтому теперь она заполняет дополнительное пространство в кадре.

Теперь для другого теста:

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

Нижняя линия все то же:

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

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

  • Нет связанных вопросов^_^