Adding a menu bar to a JSplitPane

Main.java:

 
import javax.swing.plaf.basic.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JSplitPane splitPane;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 
                                 new JPanel(), new JPanel());
      splitPane.setDividerSize(20);
  
      splitPane.setUI(new MenuDividerUI(getMainMenuBar()));
 
      getContentPane().add(splitPane);
 
      addComponentListener(new ComponentAdapter() {
         public void componentShown(ComponentEvent event) {
            splitPane.setDividerLocation(0.5);  
                
            removeComponentListener(this);
         }
      });
   }
 
   public JMenuBar getMainMenuBar() {
      JMenuBar mainBar = new JMenuBar();
      JMenu menu = new JMenu("JSplitPane");
      JMenuItem item1 = new JMenuItem("HORIZONTAL_SPLIT");
      JMenuItem item2 = new JMenuItem("VERTICAL_SPLIT");
      menu.add(item1);
      menu.add(item2);
      mainBar.add(menu);
  
      item1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
         }
      });
 
      item2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         }
      });
 
      return mainBar;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}
 
class MenuDividerUI extends BasicSplitPaneUI
{
   protected JMenuBar menuBar;
 
   public MenuDividerUI(JMenuBar menuBar) {
      this.menuBar = menuBar;
   }
 
   public BasicSplitPaneDivider createDefaultDivider() {
      BasicSplitPaneDivider divider = new BasicSplitPaneDivider(this) {
         public int getDividerSize() { return menuBar.getPreferredSize().height; }
      };
      divider.setLayout(new BorderLayout());
      divider.add(BorderLayout.NORTH, menuBar);
 
      return divider;
   }
}

Setting the JSplitPane divider location

Use the method setDividerLocation to set the divider. You can either set the new position by pixel or specify a percentage:

   // sets the divider at pixel 100
   splitPane.setDividerLocation(100);
   // sets the divider in the middle
   splitPane.setDividerLocation(.5);

The JSplitPane MUST be visible invoking this method
otherwise it will not have the desired effect. Here’s an example on how to set the divider location the moment when the JFrame becomes visible:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JSplitPane splitPane;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 
                                 new JPanel(), new JPanel());
 
      createMainMenuBar();
 
      getContentPane().add(splitPane);
 
      addComponentListener(new ComponentAdapter() {
         public void componentShown(ComponentEvent event) {
            splitPane.setDividerLocation(0.5); 
                
            removeComponentListener(this);
         }
      });
   }
 
   public void createMainMenuBar() {
      JMenuBar mainBar = new JMenuBar();
      JMenu menu = new JMenu("JSplitPane");
      JMenuItem item1 = new JMenuItem("HORIZONTAL_SPLIT");
      JMenuItem item2 = new JMenuItem("VERTICAL_SPLIT");
      menu.add(item1);
      menu.add(item2);
      mainBar.add(menu);
      setJMenuBar(mainBar);
 
      item1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
         }
      });
 
      item2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}

Get notified when the user has moved the JSplitPane divider

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JSplitPane splitPane;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      final JLabel label = new JLabel();
      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 
                                 label, new JPanel());
      splitPane.setDividerSize(20);
      splitPane.setOneTouchExpandable(true);
 
      createMainMenuBar();
 
      getContentPane().add(splitPane);
 
      addComponentListener(new ComponentAdapter() {
         public void componentShown(ComponentEvent event) {
            splitPane.setDividerLocation(0.5);  
            label.setText("Divider location: " + splitPane.getDividerLocation());
                
            removeComponentListener(this);
         }
      });
 
      splitPane.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent pce) {
            if (pce.getPropertyName().equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) {
               label.setText("Divider location: " + splitPane.getDividerLocation());
            }
         }
      });
   }
 
   public void createMainMenuBar() {
      JMenuBar mainBar = new JMenuBar();
      JMenu menu = new JMenu("JSplitPane");
      JMenuItem item1 = new JMenuItem("HORIZONTAL_SPLIT");
      JMenuItem item2 = new JMenuItem("VERTICAL_SPLIT");
      menu.add(item1);
      menu.add(item2);
      mainBar.add(menu);
      setJMenuBar(mainBar);
 
      item1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
         }
      });
 
      item2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}

Adding a JButton inside my JSplitPane divider

Main.java:

import javax.swing.plaf.basic.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JSplitPane splitPane;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 
                                 new JPanel(), new JPanel());
      splitPane.setDividerSize(20);
  
      JButton button = new JButton("Exit!");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.exit(0);
         }
      });
 
      setJMenuBar(getMainMenuBar());
 
      splitPane.setUI(new ButtonDividerUI(button));
 
      getContentPane().add(splitPane);
 
      addComponentListener(new ComponentAdapter() {
         public void componentShown(ComponentEvent event) {
            splitPane.setDividerLocation(0.5);  
                
            removeComponentListener(this);
         }
      });
   }
 
   public JMenuBar getMainMenuBar() {
      JMenuBar mainBar = new JMenuBar();
      JMenu menu = new JMenu("JSplitPane");
      JMenuItem item1 = new JMenuItem("HORIZONTAL_SPLIT");
      JMenuItem item2 = new JMenuItem("VERTICAL_SPLIT");
      menu.add(item1);
      menu.add(item2);
      mainBar.add(menu);
 
      item1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
         }
      });
 
      item2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         }
      });
 
      return mainBar;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}
 
class ButtonDividerUI extends BasicSplitPaneUI
{
   protected JButton button;
 
   public ButtonDividerUI(JButton button) {
      this.button = button;
   }
 
   public BasicSplitPaneDivider createDefaultDivider() {
      BasicSplitPaneDivider divider = new BasicSplitPaneDivider(this) {
         public int getDividerSize() { 
            if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
               return button.getPreferredSize().width; 
            }
            return button.getPreferredSize().height;
         }
      };
 
      divider.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
      divider.add(button);
 
      return divider;
   }
}

Adding a JMenuBar to the two components of a JSplitPane

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JSplitPane splitPane;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      JPanel firstPanel = createPanel();
      JPanel secondPanel = createPanel();
      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, firstPanel, secondPanel);
 
      createMainMenuBar();
 
      getContentPane().add(splitPane);
      setSize(300, 300);
      setVisible(true);
 
      splitPane.setDividerLocation(0.5); 
   }
 
   public void createMainMenuBar() {
      JMenuBar mainBar = new JMenuBar();
      JMenu menu = new JMenu("JSplitPane");
      JMenuItem item1 = new JMenuItem("HORIZONTAL_SPLIT");
      JMenuItem item2 = new JMenuItem("VERTICAL_SPLIT");
      menu.add(item1);
      menu.add(item2);
      mainBar.add(menu);
      setJMenuBar(mainBar);
 
      item1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
         }
      });
 
      item2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         }
      });
   }
 
   public JPanel createPanel() {
      JPanel panel = new JPanel();
      panel.setLayout(new BorderLayout());
      JMenuBar menuBar = new JMenuBar();
      for (int i=0; i<3; i++) {
         JMenu menu = new JMenu("JMenu " + (i+1));
         for (int j=0; j<3; j++) {
            JMenuItem item = new JMenuItem("JMenuItem " + (j+1));
            menu.add(item);
         }
         menuBar.add(menu);
      }
      panel.add(BorderLayout.NORTH, menuBar);
 
      return panel;
   }
 
   public static void main(String []args) {
      Main main = new Main();
   }
}

Using an SWT Sash

Sash is the Swing equivalent of a JSplitPane. It is a widget that can be dragged to resize two areas in a GUI.

Here’s an example of a Sash in a JFace application.

Category.java:

import java.util.*;

public class Category {
   private String name;
   private Category parent;
   private ArrayList categories = new ArrayList();
   private ArrayList links = new ArrayList();
   
   public Category(String name, Category parent) {
      this.name = name;
      this.parent = parent;
   }
   
   public void addSubCategory(Category category) {
      categories.add(category);
   }
   
   public void addLink(Link link) {
      links.add(link);
   }
   
   public ArrayList getSubCategories() {
      return categories;
   }
   
   public ArrayList getLinks() {
      return links;
   }
   
   public boolean hasSubCategories() {
      return categories.size() > 0;
   }
   
   public boolean hasLinks() {
      return links.size() > 0;
   }
   
   public String getName() {
      return name;
   }
   
   public Category getParent() {
      return parent;
   }
}

Link.java:

public class Link {
   private String url;
   
   public Link(String url) {
      this.url = url;
   }
   
   public String getUrl() {
      return url;
   }
}

CategoryTreeContentProvider.java:

import org.eclipse.jface.viewers.*;
import java.util.*;

public class CategoryTreeContentProvider implements ITreeContentProvider 
{
   public Object[] getChildren(Object element) {
      Category category = (Category) element;
      System.out.println(category.getName());
      
      ArrayList children = new ArrayList();
      children.addAll(category.getSubCategories());
      children.addAll(category.getLinks());
            
      if (children.size() == 0) {
         return new Object[0];
      }
      
      return children.toArray();
   }
   
   public Object[] getElements(Object element) {
      return getChildren(element);
   }
   
   public boolean hasChildren(Object element) {
      if (element instanceof Category) {
         Category category = (Category) element;
      
         return category.hasSubCategories() || category.hasLinks();
      }
      
      return false;
   }
   
   public Object getParent(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getParent();
      }
      
      return null;
   }
   
   public void dispose() {
      
   }
   
   public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      
   }
}

CategoryTreeLabelProvider.java:

import org.eclipse.jface.viewers.*;

public class CategoryTreeLabelProvider extends LabelProvider
{
   public String getText(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getName();
      }
      else if (element instanceof Link) {
         return ((Link) element).getUrl();
      }
      
      return "" + element;
   }
}

Main.java:

import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleControlSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

public class Main extends ApplicationWindow 
{
   private Category rootCategory;
   private OleAutomation automation = null;
   
   public Main() {
      super(null);
      
      // statically create categories
      rootCategory = new Category("Java", null);
      Category j2seCategory = new Category("J2SE", rootCategory);
      Link link = new Link("http://java.sun.com/j2se/");
      j2seCategory.addLink(link);
      Category j2eeCategory = new Category("J2EE", rootCategory);
      link = new Link("http://java.sun.com/j2ee/");
      j2eeCategory.addLink(link);
      Category j2meCategory = new Category("J2ME", rootCategory);
      link = new Link("http://java.sun.com/j2me/");
      j2meCategory.addLink(link);
      
      rootCategory.addSubCategory(j2seCategory);
      rootCategory.addSubCategory(j2eeCategory);
      rootCategory.addSubCategory(j2meCategory);
   }
   
   protected Control createContents(Composite parent) {
      SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL | SWT.NULL);
      
      TreeViewer treeViewer = new TreeViewer(sashForm);
      treeViewer.setContentProvider(new CategoryTreeContentProvider());
      treeViewer.setLabelProvider(new CategoryTreeLabelProvider());
      treeViewer.setInput(rootCategory);
      
      createIEControl(sashForm);
      
      treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
         public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            
            Object selectedObject = selection.getFirstElement();
            if (selectedObject instanceof Link) {
               goUrl(((Link) selectedObject).getUrl());  
            }
         }
      });
      
      return sashForm;
   }
   
   public static void main(String []args) {
      Main main = new Main();
      main.setBlockOnOpen(true);
      main.open();
      
      Display.getCurrent().dispose();
   }
   
   private void createIEControl(Composite parent) {     
      OleFrame frame = new OleFrame(parent, SWT.BORDER);
      FormData formData = new FormData();
      formData.top = new FormAttachment(0, 10);
      formData.left = new FormAttachment(0, 100);
      formData.right = new FormAttachment(100, 0);
      formData.bottom = new FormAttachment(100, -10);
      frame.setLayoutData(formData);
   
      OleControlSite controlSite = new OleControlSite(frame, SWT.NONE, "Shell.Explorer");
      controlSite.doVerb(OLE.OLEIVERB_SHOW);
      automation = new OleAutomation(controlSite);
      int[] rgdispid = automation.getIDsOfNames(new String[]{"GoHome"});
      int dispIdMember = rgdispid[0];
      automation.invoke(dispIdMember);
   }
   
   public void goUrl(String url) {
      int[] rgdispid = automation.getIDsOfNames(new String[]{"Navigate"});
      int dispIdMember = rgdispid[0];
      Variant[] rgvarg = new Variant[1]; // this is the URL parameter
      rgvarg[0] = new Variant(url);
      Variant pVarResult = automation.invoke(dispIdMember, rgvarg);      
   }   
}