Question

I have JSplitPane that has oneTouchExpandable set to true.

JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPane.setDividerSize(10);
        splitPane.setOneTouchExpandable(true);

The problem is that I do not know how to attach key bindings to up and down arrows on JSplitPane's divider. For up arrow I want Ctrl+U and for down - Ctrl + D.

Thanks!

Was it helpful?

Solution 2

The problem is that I do not know how to attach key bindings to up and down arrows on JSplitPane's divider.

Normally you would try to access the Action of the button. In many cases the component will already define an Action that you can use. See Key Bindings for a list of the default bindings for a JSplitPane. Unfortunately there is no Action to support the one touch clicking options.

So we need to access the buttons directly from the UI:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class SplitPaneDividerAction extends AbstractAction
{
    private boolean leading;

    public SplitPaneDividerAction(boolean leading)
    {
        this.leading = leading;
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        JSplitPane splitPane = (JSplitPane)e.getSource();
        BasicSplitPaneUI ui = (BasicSplitPaneUI)splitPane.getUI();
        BasicSplitPaneDivider divider = ui.getDivider();

        if (leading)
            ((JButton)divider.getComponent(0)).doClick();
        else
            ((JButton)divider.getComponent(1)).doClick();
    }

    private static void createAndShowUI()
    {
        JPanel leading = new JPanel();
        leading.setPreferredSize( new Dimension(200, 100) );
        leading.setBackground( Color.BLUE );
        leading.setFocusable(true);

        JPanel trailing = new JPanel();
        trailing.setPreferredSize( new Dimension(200, 100) );
        trailing.setBackground( Color.RED );
        trailing.setFocusable(true);

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leading, trailing);
        splitPane.setOneTouchExpandable(true);
        splitPane.setDividerLocation(100);

        InputMap im = splitPane.getInputMap(JSplitPane.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        ActionMap am = splitPane.getActionMap();
        im.put(KeyStroke.getKeyStroke("control U"), "leading");
        im.put(KeyStroke.getKeyStroke("control D"), "trailing");
        am.put("leading", new SplitPaneDividerAction(true));
        am.put("trailing", new SplitPaneDividerAction(false));

        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( splitPane );
        frame.setSize(200, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

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

Of course this approach will only work if your LAF extends from the BasicSplitPaneUI.

OTHER TIPS

Implementation of the arrow button shown by OneTouchExpandable is UI label and will take extra work unnecessarily to bind them. You can easily use Key Binding on JSplitPane itself to control the JSplitPane divider location using setDividerLocation(int). Increase on Ctrl + U and Decrease on Ctrl + D. For example:

    Action incrDividerLoc = new AbstractAction() {
    public void actionPerformed(ActionEvent e) {
        JSplitPane srcSplitPan = (JSplitPane) e.getSource();
        (srcSplitPan).setDividerLocation(srcSplitPan.getDividerLocation()+10);
     }
   };

  Action decrDividerLoc = new AbstractAction() {
    public void actionPerformed(ActionEvent e) {
        JSplitPane srcSplitPan = (JSplitPane) e.getSource();
        (srcSplitPan).setDividerLocation(srcSplitPan.getDividerLocation()-10);
    }
   };

    jSplitPane1.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK),
                                "increaseDivider");
    jSplitPane1.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.CTRL_DOWN_MASK),
                                "decreaseDivider");
    jSplitPane1.getActionMap().put("increaseDivider", incrDividerLoc);
    jSplitPane1.getActionMap().put("decreaseDivider", decrDividerLoc);

Note: method A value less than 0 passed to setDividerLocation(int) implies the divider should be reset to a value that attempts to honor the preferred size of the left/top component. After notifying the listeners, the last divider location is updated, via setLastDividerLocation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top