2011-02-08 17 views
6

Ho un JFrame con un JSplitPane che è OneTouchExpandable. Voglio ricordare l'ultima posizione di Divider di JSplitPane su JFrame e ripristinare la posizione se viene riaperto il JFrame.Come impostare JSplitPane-Divider comprimere/espandere stato?

funziona bene, ma se l'utente espandere un lato attraverso il oneTouchExpandable UI-Widget poi ho memorizzare solo il 'int'-Posizione sulla smaltire e impostare il' int'-Position di nuovo con la conseguenza sul JFrame- il ridimensionamento di JSplitPane-Divider salta al preferredSize del componente compresso.

Come posso ottenere/impostare la compressione/espandi stato?

EDIT

Ora: il ridimensionamento-comportamento è OK, ma non è esattamente lo stesso comportamento come la prima volta aperta - perché ora non ho MinimumDividerLocation. Volevo lo SnapIn, ma ulteriormente il 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); 
    } 
} 

risposta

11

ho trovato che è possibile a crollare un lato della SplitPane impostando la dimensione minima del componente per new Dimension() e quindi impostare la posizione di divisione:

// 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); 

si può giocare con queste impostazioni per memorizzare e ripristina lo stato di compressione/espansione.

+0

sì, il ridimensionamento-Behavior è OK, ma non è esattamente lo stesso comportamento come la prima volta aperta - perché ora non ho MinimumDividerLocation. Volevo lo SnapIn, ma ulteriormente il collapsedState. – oliholz

+0

Dopo aver provato varie soluzioni proposte, ho trovato la seguente soluzione funzionante: '' pane.getRightComponent(). SetMinimumSize (new Dimension()); pane.setResizeWeight (1.0 d); '' –

+0

Questo ha funzionato per me (grazie! :)) ma la posizione del divisore non si attacca quando ridimensionata, specialmente quando non è possibile sovrascrivere la dimensione minima del componente. Vedi la mia risposta per hackerarlo se usi 'BasicSplitPaneUI'. – Matthieu

0

JSplitPane ha un metodo setDividerLocation (doppia), che definisce la posizione divisore come percentuale delle dimensioni del JSplitPane. Ho provato a creare funzionalità simili qualche tempo fa. Ho avuto lo stesso problema. Ma anche quando utilizzo il metodo setDividerLocation (double), non ha funzionato correttamente. Credo che sia solo un bug di JSplitPane.

0

Nasconde la finestra di dialogo/frame un'opzione?

// 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

si prega di fornire una breve spiegazione alla risposta. –

1

I migliorata versione della levetta funzioni:

/** 
* 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 vuoto (doppia proportionalLocation)

Imposta il divisore posizione in percentuale età della dimensione di JSplitPane. Questo metodo è implementato in termini di setDividerLocation (int). Questo metodo modifica immediatamente la dimensione di il riquadro diviso in base alla sua dimensione corrente. Se il riquadro diviso non è correttamente realizzato e visualizzato sullo schermo, questo metodo non avrà alcun effetto (la nuova posizione del divisore diventerà (dimensione corrente * posizione proporzionale) che è 0).

Quindi, in pratica è necessario aver creato tutta l'interfaccia utente, chiamato .Pack() sul JFrame principale e dopo che è possibile utilizzare JSplitPane.setDividerLocation (doppio). Se lo fai prima che il layout dell'interfaccia utente e tutto ciò che è fatto, il metodo non farà nulla come afferma nella documentazione e hai già sperimentato.

1

Forzare la posizione del divisore su un valore molto piccolo/grande per nascondere il componente superiore/inferiore, ma viene disattivato quando il riquadro diviso viene ridimensionato, a causa della dimensione minima del componente. L'impostazione di tale dimensione su 0 (come proposto nella risposta accettata) funziona, ma ci sono casi in cui non puoi/non vuoi sovrascriverlo.

Dopo aver esaminato il BasicSplitPaneUI e le classi associate, risulta che i pulsanti "espansione a un tocco" chiamano BasicSPlitPaneUI.setKeepHidden(true), quindi il divisore si attaccherà a entrambe le estremità una volta ridimensionato.

Sfortunatamente, questo metodo è il pacchetto-privato, ma l'impostazione del keepHidden campo associato può essere fatto utilizzando l'introspezione, 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