2014-09-17 4 views
1

Если я настроил JFrame с некоторыми компонентами и менеджером компоновки, который изначально выглядит отлично, а затем позже из-за некоторого состояния (например, нажав кнопку), я скрою один из этих компонентов - менеджер компоновки перетасовывает все компоненты снова вокруг.Скрыть компонент качания без повторной калибровки макета?

См. Пример кода - изначально отображаются 3 кнопки. Когда вы нажимаете кнопку «Скрыть», кнопка «Скрыть» скрыта, но две внешние кнопки скручиваются вместе. Когда вы нажимаете кнопку «Показать», они снова разворачиваются, чтобы освободить место. Как я могу остановить это, чтобы после того, как я вызвал пакет(), компоненты останутся там, где они не имеют значения, если они позже станут скрытыми?

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

Я могу только думать о неприятных способах этого, например, использовать .setEnabled (false) вместо .setVisible (false), а затем переопределять метод paintComponent() компонента, чтобы не рисовать компонент при его отключении.

кажется точной проблема, противоположной здесь - Hide a button from Layout in Java Swing - где жалуются, что скрытые кнопки сделать все еще занимает место :) Но нет никакого образца кода там, чтобы показать, что работает таким образом.

Большое спасибо за любые предложения :)

Пример:

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 

import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class RevalidateWhenSetChildInvisibleExample 
{ 
    private JButton button1; 
    private JButton button2; 
    private JButton button3; 

    public void run() 
    { 
     // Set up action 
     Action hideButtonAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed (ActionEvent e) 
      { 
       button2.setVisible (false); 
      } 
     }; 
     hideButtonAction.putValue (Action.NAME, "Hide"); 

     Action showButtonAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed (ActionEvent e) 
      { 
       button2.setVisible (true); 
      } 
     }; 
     showButtonAction.putValue (Action.NAME, "Show"); 

     // Set up buttons 
     button1 = new JButton ("Dummy"); 
     button2 = new JButton (hideButtonAction); 
     button3 = new JButton (showButtonAction); 

     // Set up content pane 
     JPanel contentPane = new JPanel(); 
     contentPane.setLayout (new FlowLayout()); 
     contentPane.add (button1); 
     contentPane.add (button2); 
     contentPane.add (button3); 

     // Set up frame 
     JFrame frame = new JFrame(); 
     frame.setContentPane (contentPane); 
     frame.pack(); 
     frame.setVisible (true); 
    } 

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

ответ

4

Вы можете использовать CardLayout и переставить кнопку с пустой JPanel.

Для получения дополнительной информации и примеров ознакомьтесь с разделом из учебника Swing по телефону How to Use CardLayout.

+0

Да, я много использовал CardLayouts, но не для этого сценария. Его действительно неплохая идея, потому что CardLayout будет определять размер в соответствии с кнопкой (или что-то еще), даже если кнопка не видна, поэтому она не хочет злоупотреблять менеджером компоновки. – nigelg

+0

Я построил класс HideableComponent, который делает именно это - обертывает любой компонент в панели с помощью cardlayout, поэтому может просто вызвать .setHidden (true/false) на нем, поэтому его не нужно знать, что под обложками он реализуется через CardLayout , и он отлично работает :), так можно сделать, например новый HideableComponent (новый JButton (действие)).Если вас интересует код - https://sourceforge.net/p/momime/code/HEAD/tree/Java/MoMIMEClient/trunk/src/main/java/momime/client/ui/components/HideableComponent.java – nigelg

1

Проблема заключается в менеджере компоновки, который здесь не является проблемой, потому что он просто выполняет свою работу. Вы можете установить макет null, а затем установить границы для каждой кнопки; таким образом они НИКОГДА не будут двигаться, если вы не измените свое положение.

panel.setLayout(null); 
button1.setBounds(10,10,50,20); 
button2.setBounds(70,10,50,20); 
button3.setBounds(xPos,yPos,width,height); 

Другой способ заключается в использовании GridLayout:

contentPane.setLayout(new GridLayout()); 

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

Кроме того, вы должны добавить следующие строки в ваш код:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

Это делает выходы программы, когда JFrame закрыта; без него программа все еще работает на заднем плане.