2011-02-08 9 views
6

Tengo un JFrame con un JSplitPane que es OneTouchExpandable. Quiero recordar la última posición del Divisor del JSplitPane en JFrame disponer y restaurar la Posición si el JFrame se vuelve a abrir.Cómo establecer JSplitPane-Divider colapsar/expandir Estado?

funciona bien, pero si el usuario expanda un lado a través de la interfaz de usuario oneTouchExpandable-Widget continuación almaceno sólo el 'int'-Posición de disponer y establezca el' int'-Posición de nuevo con la consecuencia de JFrame- el cambio de tamaño del JSplitPane-Divider salta al Componente preferredSize contraído.

¿Cómo puedo obtener/configurar el estado de colapso/expansión?

EDITAR

Ahora: el cambio de tamaño en el comportamiento está bien, pero no es exactamente el mismo comportamiento como el primer tiempo abierto - porque ahora no tengo MinimumDividerLocation. Yo quería el SnapIn, pero además el collapsedState.

public class SplitPaneState { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new SplitPaneState().createAndSowGUI(); 
      } 
     }); 
    } 

    private int position = -1; 
    private Dimension size = new Dimension(500, 300); 

    private void createAndSowGUI() { 
     final JFrame frame = new JFrame("frame"); 
     frame.setSize(200, 100); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.getContentPane().add(new JButton(new AbstractAction(){ 
      { 
       putValue(Action.NAME, "Open Dialog"); 
      } 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JLabel("left Component"), new JLabel("right Component")); 
       splitPane.setContinuousLayout(true); 
       splitPane.setOneTouchExpandable(true); 
       if(position != -1) { 
        boolean LeftIsCollapsed = position < splitPane.getMinimumDividerLocation(); 
        if(LeftIsCollapsed) { 
         splitPane.getLeftComponent().setMinimumSize(new Dimension()); // fix by Martijn Courteaux 
         splitPane.setDividerLocation(0.0d);       // fix by Martijn Courteaux 
        }else { 
         splitPane.setDividerLocation(position); 
        } 
       } 
       JDialog dialog = new JDialog(frame,"dialog"){ 
        @Override 
        public void dispose() { 
         position = splitPane.getDividerLocation(); 
         size = this.getSize(); 
         super.dispose(); 
        } 
       }; 
       dialog.setSize(size); 
       dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       dialog.setLocationRelativeTo(frame); 
       dialog.getContentPane().add(splitPane); 
       dialog.setVisible(true); 
       } 
      } 
     )); 
     frame.setVisible(true); 
    } 
} 

Respuesta

11

He descubierto que es posible colapsar un lado de la SplitPane ajustando el tamaño mínimo del componente a new Dimension() y luego establecer la ubicación del divisor:

// Hide left or top 
pane.getLeftComponent().setMinimumSize(new Dimension()); 
pane.setDividerLocation(0.0d); 

// Hide right or bottom 
pane.getRightComponent().setMinimumSize(new Dimension()); 
pane.setDividerLocation(1.0d); 

se puede jugar con estos ajustes para almacenar y restablecer el estado de colapso/expansión.

+0

sí, el cambio de tamaño en el comportamiento está bien, pero no es exactamente el mismo comportamiento como la primera vez abierta, porque ahora no tengo MinimumDividerLocation. Yo quería el SnapIn, pero además el collapsedState. – oliholz

+0

Después de probar varias soluciones propuestas, encontré la siguiente solución para trabajar: '' pane.getRightComponent(). SetMinimumSize (new Dimension()); pane.setResizeWeight (1.0d); '' –

+0

Eso funcionó para mí (¡gracias! :)) pero la posición del divisor no se pega al cambiar el tamaño, especialmente cuando no puede anular el tamaño mínimo del componente. Ver mi respuesta para hackear si usa 'BasicSplitPaneUI'. – Matthieu

0

JSplitPane tiene un método setDividerLocation (doble), que establece la ubicación divisor como un porcentaje del tamaño de la JSplitPane. Intenté crear una funcionalidad similar hace algún tiempo. Yo tuve el mismo problema. Pero incluso cuando uso el método setDividerLocation (double), no funcionó correctamente. Creo que es solo un error de JSplitPane.

0

¿Está ocultando su cuadro de diálogo/marco una opción?

// Create the dialog/frame which contains the JSplitPane 
final JFrame frame = new JFrame("JSplitPane Problem"); 
frame.setCloseOperation(JFrame.HIDE_ON_CLOSE); 
// ... 
myButton.addActionListener(new ActionListener() 
{ 
    public void actionPerformed(ActionEvent ae) 
    { 
     if (!frame.isVisible()) 
      frame.setVisible(true); 
    } 

}); 
0
public static void toggle(JSplitPane sp, boolean collapse) { 
     try { 
      BasicSplitPaneDivider bspd = ((BasicSplitPaneUI) sp.getUI()).getDivider(); 
      Field buttonField = BasicSplitPaneDivider.class. 
        getDeclaredField(collapse ? "rightButton" : "leftButton"); 
      buttonField.setAccessible(true); 
      JButton button = (JButton) buttonField.get(((BasicSplitPaneUI) sp.getUI()).getDivider()); 
      button.getActionListeners()[0].actionPerformed(new ActionEvent(bspd, MouseEvent.MOUSE_CLICKED, 
        "bum")); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
+1

por favor brinde una breve explicación de su respuesta. –

1

Me mejorada versión de una función activar:

/** 
* toggle JSplitPane 
* @param sp - splitpane to toggle 
* @param upLeft - is it left or top component to collapse? or button or right 
* @param collapse - true component should be collapsed 
*/ 
public void toggle(JSplitPane sp, boolean upLeft, boolean collapse) { 
    try { 
     //get divider object 
     BasicSplitPaneDivider bspd = ((BasicSplitPaneUI) sp.getUI()).getDivider(); 
     Field buttonField; 

     //get field button from divider 
     if (upLeft) { 
      if (collapse != (sp.getDividerLocation() < sp.getMinimumDividerLocation())) { 
       return; 
      } 
      buttonField = BasicSplitPaneDivider.class.getDeclaredField(collapse ? "rightButton" : "leftButton"); 
     } else { 
      if (collapse != (sp.getDividerLocation() > sp.getMaximumDividerLocation())) { 
       return; 
      } 

      buttonField = BasicSplitPaneDivider.class.getDeclaredField(collapse ? "leftButton" : "rightButton"); 
     } 
     //allow access 
     buttonField.setAccessible(true); 
     //get instance of button to click at 
     JButton button = (JButton) buttonField.get(((BasicSplitPaneUI) sp.getUI()).getDivider()); 
     //click it 
     button.doClick(); 
     //if you manage more dividers at same time before returning from event, 
     //you should update layout and ui, otherwise nothing happens on some dividers: 
     sp.updateUI(); 
     sp.doLayout(); 


    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
0

http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html

javax.swing.JSplitPane.setDividerLocation vacío (doble proportionalLocation)

Establece el divisor ubicación como un porcentaje edad del tamaño JSplitPane. Este método se implementa en términos de setDividerLocation (int). Este método cambia inmediatamente el tamaño de el panel dividido en función de su tamaño actual. Si el panel dividido no está correctamente realizado y en la pantalla, este método no tendrá ningún efecto (la nueva ubicación del divisor se convertirá en (tamaño actual * ubicación proporcional) que es 0).

Así que, básicamente, es necesario haber creado toda la interfaz de usuario, llamado .Pack() en el JFrame principal y después de que se puede utilizar JSplitPane.setDividerLocation (doble). Si lo haces antes del diseño de UI y todo eso está hecho, el método simplemente no hará nada como lo indica en la documentación y ya lo experimentaste.

1

Forzando la posición del divisor a un valor muy pequeño/grande para ocultar el componente superior/inferior funciona, pero se anula cuando el panel dividido se redimensiona, debido al tamaño mínimo del componente. Establecer ese tamaño en 0 (como se propone en la respuesta aceptada) funciona, pero hay casos en los que no puede/no desea anularlo.

Después de mirar en el BasicSplitPaneUI y las clases asociadas, resulta que los botones de "expansión de un toque" están llamando a BasicSPlitPaneUI.setKeepHidden(true), por lo que el divisor se pegará a cualquiera de los extremos al cambiar el tamaño.

Por desgracia, ese método es el paquete-privado, pero estableciendo el keepHidden campo asociado se puede hacer uso de la introspección, as shown in another answer:

sp.setDividerLocation(<0 or 999999>); // Divider is positioned at the top/bottom 
Field m = BasicSplitPaneUI.class.getDeclaredField("keepHidden"); 
m.setAccessible(true); 
m.set(sp.getUI(), true); // Divider position will stick 
Cuestiones relacionadas