【问题标题】:Why JScrollBar doesn't respond to arrow keystrokes when coexist with editable component?为什么 JScrollBar 在与可编辑组件共存时不响应箭头键击?
【发布时间】:2013-10-17 14:51:29
【问题描述】:

(说明后代码中会很清楚)

我有一个包含 JScrollBar、JTextArea、JTextFields、JButtons 和其他一些东西的程序。 (我只加了SSCCE代码)

好的,我为 JScrollBar 的左右 JButtons 添加了键绑定,我使用 getInputMapgetActionMap 来实现。

如果我的 GUI 程序中的 JScrollBar 没有 JTextField 或 JTextArea 等可编辑组件,那么 keyStrokes KeyEvent.VK_LEFTKeyEvent.VK_RIGHT 将正常工作(如预期)

但是,如果我有一个带有 JScrollBar 的可编辑组件,那么它不会响应 KeyEvent.VK_LEFTKeyEvent.VK_RIGHT(不是预期的)为什么会发生这种情况!?
更奇怪的事情是,如果我选择不同的 keyStrokes 来绑定,例如 KeyEvent.VK_S 用于左侧,KeyEvent.VK_F 用于右侧,它将起作用!现在为什么?

如何解决,在可编辑组件共存的情况下,如何让JScrollBar JButtons左右箭头键绑定?

这是 SSCCE 风格的两个工作代码。第一个包含没有可编辑组件的 JScrollBar,第二个包含带有 JTextArea 的 JScrollBar。

第一个可以正常工作,它会响应键盘的左右箭头。 (它不包含可编辑的组件)

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

public class ScrollTest extends JPanel
{

   JPanel panel;
   JScrollBar scrollBar;
   JButton sliderLeftButton;
   JButton sliderRightButton;

   public ScrollTest()
   {
      scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 6, 0, 300);

      sliderLeftButton = (JButton) scrollBar.getAccessibleContext().getAccessibleChild(1);
      sliderLeftButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "leftmove");
      sliderLeftButton.getActionMap().put("leftmove", leftmove);

      sliderRightButton = (JButton) scrollBar.getAccessibleContext().getAccessibleChild(0);
      sliderRightButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "rightmove");
      sliderRightButton.getActionMap().put("rightmove", rightMove);

      panel = new JPanel(new GridLayout(2, 0));
      panel.add(scrollBar);

      this.setLayout(new BorderLayout());
      this.add(panel, BorderLayout.NORTH);
   }
   AbstractAction leftmove = new AbstractAction()
   {
      @Override
      public void actionPerformed(ActionEvent ae)
      {
         int increment = scrollBar.getBlockIncrement();
         int current = scrollBar.getValue();
         current -= increment;
         scrollBar.setValue(current);
         System.out.println("left");
      }
   };
   AbstractAction rightMove = new AbstractAction()
   {
      @Override
      public void actionPerformed(ActionEvent ae)
      {
         int increment = scrollBar.getBlockIncrement();
         int current = scrollBar.getValue();
         current += increment;
         scrollBar.setValue(current);
         System.out.println("right");
      }
   };

   private static void createAndShowGUI()
   {
      JFrame frame;
      frame = new JFrame("Scroll Test");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(880, 100);
      frame.add(new ScrollTest(), BorderLayout.CENTER);
      frame.setVisible(true);
   }

   public static void main(String[] args)
   {
      SwingUtilities.invokeLater(new Runnable()
      {
         public void run()
         {
            UIManager.put("swing.boldMetal", Boolean.FALSE);
            createAndShowGUI();
         }
      });
   }
}

第二个将起作用,即它不会响应键盘的左右箭头。 (它确实包含可编辑的组件 - 一个 JTextArea)

更奇怪的事情
KeyEvent.VK_LEFT 替换为KeyEvent.VK_S 并将KeyEvent.VK_RIGHT 替换为KeyEvent.VK_F。现在 S 将适用于左侧,而 F 将适用于右侧!为什么它不能与左右箭头一起使用。

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

public class ScrollTest extends JPanel
{

   JPanel panel;
   JPanel panel2;
   JScrollBar scrollBar;
   JButton sliderLeftButton;
   JButton sliderRightButton;

   public ScrollTest()
   {
      scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 6, 0, 300);

      sliderLeftButton = (JButton) scrollBar.getAccessibleContext().getAccessibleChild(1);
      sliderLeftButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "leftmove");
      sliderLeftButton.getActionMap().put("leftmove", leftmove);

      sliderRightButton = (JButton) scrollBar.getAccessibleContext().getAccessibleChild(0);
      sliderRightButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "rightmove");
      sliderRightButton.getActionMap().put("rightmove", rightMove);

      panel = new JPanel(new GridLayout(2, 0));
      panel.add(scrollBar);

      panel2 = new JPanel(new GridLayout(1, 0));
      panel2.add(new JTextArea(50, 10));

      this.setLayout(new BorderLayout());
      this.add(panel, BorderLayout.NORTH);
      this.add(panel2, BorderLayout.SOUTH);
   }
   AbstractAction leftmove = new AbstractAction()
   {
      @Override
      public void actionPerformed(ActionEvent ae)
      {
         int increment = scrollBar.getBlockIncrement();
         int current = scrollBar.getValue();
         current -= increment;
         scrollBar.setValue(current);
         System.out.println("left");
      }
   };
   AbstractAction rightMove = new AbstractAction()
   {
      @Override
      public void actionPerformed(ActionEvent ae)
      {
         int increment = scrollBar.getBlockIncrement();
         int current = scrollBar.getValue();
         current += increment;
         scrollBar.setValue(current);
         System.out.println("right");
      }
   };

   private static void createAndShowGUI()
   {
      JFrame frame;
      frame = new JFrame("Scroll Test");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(880, 100);
      frame.add(new ScrollTest(), BorderLayout.CENTER);
      frame.setVisible(true);
   }

   public static void main(String[] args)
   {
      SwingUtilities.invokeLater(new Runnable()
      {
         public void run()
         {
            UIManager.put("swing.boldMetal", Boolean.FALSE);
            createAndShowGUI();
         }
      });
   }
}

【问题讨论】:

  • 在我看来,您必须使用 JComponent.WHEN_IN_FOCUSED_WINDOWInputMap 的这个属性。由于相同的KeyBindings 事物也适用于可编辑的JTextField/JTextArea,因此您必须将getInputMap().put() 的此事物留空。简单来说,相同的键也绑定到可编辑的JTextField/JTextArea,因此WHEN_FOCUSED 将优先于WHEN_IN_FOCUSED_WINDOW恕我直言,正如KeyBindings 教程中所述:-)
  • @Andrew 最好编辑它而不是讽刺地评论英语的滥用,因为英语不是我的第一语言,这就是我试图用英语表达事物的方式。我总是尽力做到最好。谢谢
  • 默认情况下可编辑组件需要基于键的导航。正如@nIcEcOw 所详述的那样,将滚动条和可编辑组件的键绑定放在一起是反直觉的(更改滚动以响应 V 或 S 或将可编辑组合滚动更改为 V 或 S)。在可编辑组件中时,让滚动条移动由鼠标控制。

标签: java swing binding keystroke jscrollbar


【解决方案1】:

这是因为 JTextArea 正在窃取您的击键:

    textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "pressed RIGHT");
    textPane.getActionMap().put("pressed RIGHT", rightMove);

看看 BasicTextUI.installKeyboardActions()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-03
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多