与可编辑组件共存时,为什么JScrollBar不响应箭头键? - java

(说明后代码中的内容将很清楚)

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

好的,我为JScrollBar的左右JButton添加了键绑定,我使用了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 JButton制作左右箭头的键绑定?

这是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();
         }
      });
   }
}

java大神给出的解决方案

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

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

看看BasicTextUI.installKeyboardActions()

如何在Java中以语言环境正确的顺序格式化日期和月份? - java

有没有一种方法可以用Java / Kotlin中的区域设置正确的格式格式化日和月(以紧凑格式)而不格式化年份?因此,对于英语,应为“ 9月20日”,而对于瑞典语为“ 9月20日”。为了进行比较,在Cocoa平台上,我可以执行以下操作(在Swift中):let formatter = DateFormatter() formatter.locale = Loc…

DataSourceTransactionManager和JndiObjectFactoryBean和JdbcTemplate的用途是什么? - java

以下的用途是什么:org.springframework.jdbc.core.JdbcTemplate org.springframework.jdbc.datasource.DataSourceTransactionManager org.springframework.jndi.JndiObjectFactoryBean <tx:annotatio…

如何修改休眠的SQL查询? - java

我有点好奇,有没有办法修改hibernate的核心,以便我可以自定义生成的SQL query。例如,在生成的查询中添加功能以使用connect by prior(oracle)或我要自定义的任何其他子句。 java大神给出的解决方案 起初,这样的问题总是在我心中敲响警钟。你被警告了...AFAIK,hibernate使用所谓的dialects进行特定的优化。…

用Java构建大批量数据处理工具 - java

Closed. This question needs to be more focused。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。 3年前关闭。 Improve this question 我正在尝试使用Java构建ETL工具。 ETL工具用于对大量数据(关系型和其他类型)进行批量读取,…

用Java封装对象? - java

private中的Java提供类级别的封装。可以封装一个对象吗?还是这样做徒劳?例如,如果我们将一个类定义为 public class Person { private String ssn; private ArrayList<Person> friends = new ArrayList<Person>(); public voi…