【问题标题】:How to attach key binding to up and down arrows of JSplitPane divider?如何将键绑定附加到 JSplitPane 分隔符的向上和向下箭头?
【发布时间】:2013-11-01 14:28:23
【问题描述】:

我的 JSplitPane 将 oneTouchExpandable 设置为 true。

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

问题是我不知道如何将键绑定附加到 JSplitPane 分隔符上的向上和向下箭头。对于向上箭头,我想要 Ctrl+U,对于向下 - Ctrl + D。

谢谢!

【问题讨论】:

    标签: java swing key-bindings jsplitpane


    【解决方案1】:

    问题是我不知道如何将键绑定附加到 JSplitPane 分隔器上的向上和向下箭头。

    通常您会尝试访问按钮的操作。在许多情况下,组件已经定义了您可以使用的 Action。有关 JSplitPane 的默认绑定列表,请参阅 Key Bindings。不幸的是,没有支持一键点击选项的操作。

    所以我们需要直接从 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();
                }
            });
        }
    }
    

    当然,这种方法只有在您的 LAF 从 BasicSplitPaneUI 扩展时才有效。

    【讨论】:

      【解决方案2】:

      OneTouchExpandable 显示的箭头按钮的实现是 UI 标签,需要额外的工作来绑定它们。您可以轻松地使用JSplitPane 本身上的键绑定来使用setDividerLocation(int) 控制JSplitPane 分隔线位置。增加Ctrl + U 并减少Ctrl + D。例如:

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

      注意: 方法 传递给setDividerLocation(int) 的值小于0 意味着分隔符应重置为尝试遵循左/上组件的首选大小的值。通知听众后,最后一个分隔线的位置被更新,通过setLastDividerLocation

      【讨论】:

      • +1,但拆分窗格引用应该来自 ActionEvent 的 getSource() 方法。
      • @camickr,但我还是会听你的。 :) 已编辑
      最近更新 更多