使用箭头键浏览JButton

4
我已经创建了一个JButton数组,代表卡片,共有16个,4x4的排列方式。如何使用键盘上的箭头浏览JButton,而不是使用鼠标,并且如何通过按下ENTER键来“点击”JButton,而不是使用鼠标单击?也许有其他方法可以代替使用JButton吗?
最好的问候!

1
默认情况下,所有按钮都可以使用<space>进行单击。此外,您还可以使用<tab>和<shift-tab>在按钮之间导航,但是您只能向右移动到四行,然后将转到下一行的四个按钮。 - toto2
实际上,正如我在下面学到的那样...根据你的Swing外观和感觉,有时候<enter>键是默认激活按钮的键,而不是<space>键。 - toto2
6个回答

8
我已经创建了一个方案,可以让你使用箭头键导航按钮,并用空格和回车键激活它们。
以下是全部代码。没有提供注释,如果有任何问题,请告诉我。
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ButtonPane extends JPanel {

   private JButton[][] buttons;

   public ButtonPane(int row, int col) {
      super(new GridLayout(row, col));
      buttons = new JButton[row][col];
      for (int i = 0; i < buttons.length; i++) {
         for (int j = 0; j < buttons[i].length; j++) {
            final int curRow = i;
            final int curCol = j;
            buttons[i][j] = new JButton(i + ", " + j);
            buttons[i][j].addKeyListener(enter);
            buttons[i][j].addKeyListener(new KeyAdapter() {
               @Override
               public void keyPressed(KeyEvent e) {
                  switch (e.getKeyCode()) {
                  case KeyEvent.VK_UP:
                     if (curRow > 0)
                        buttons[curRow - 1][curCol].requestFocus();
                     break;
                  case KeyEvent.VK_DOWN:
                     if (curRow < buttons.length - 1)
                        buttons[curRow + 1][curCol].requestFocus();
                     break;
                  case KeyEvent.VK_LEFT:
                     if (curCol > 0)
                        buttons[curRow][curCol - 1].requestFocus();
                     break;
                  case KeyEvent.VK_RIGHT:
                     if (curCol < buttons[curRow].length - 1)
                        buttons[curRow][curCol + 1].requestFocus();
                     break;
                  default:
                     break;
                  }
               }
            });
            add(buttons[i][j]);
         }
      }
   }

   private KeyListener enter = new KeyAdapter() {
      @Override
      public void keyTyped(KeyEvent e) {
         if (e.getKeyChar() == KeyEvent.VK_ENTER) {
            ((JButton) e.getComponent()).doClick();
         }
      }
   };

   public static void main(String[] args) {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.add(new ButtonPane(4, 4));
      f.pack();
      f.setVisible(true);
   }
}

要运行此程序,只需将其粘贴到名为ButtonPane的类中即可。
这里重要的部分是在调用箭头键时,在正确的JButton上调用requestFocus()。我还注册了一个额外的KeyListener来处理按下Enter键的情况。

2
只需在键盘上按下 Enter 键即可... 确保使用。
button.addActionListener(yourActionListener);

不需要创建鼠标监听器。

哦,我忘了另一部分。 :D

对于浏览,您可以使用button.requestFocus()将焦点更改到特定按钮。

这里是一些示例代码:

final JButton matrix[][] = new JButton[4][4];
for (int x = 0; x < 4; ++x)
{
    for (int y = 0; y < 4; ++y)
    {
        final int xx = x;
        final int yy = y;
        JButton b = new JButton();
        b.addKeyListener(new KeyAdapter()
        {
            @Override
            public void keyPressed(KeyEvent e)
            {
                int c = e.getKeyCode();
                if (c == KeyEvent.VK_UP)
                {
                    // Oops, corrected (xx > 0) to (yy > 0)
                    if (yy > 0) matrix[xx][yy-1].requestFocus();
                } else if (c == KeyEvent.VK_DOWN)
                {
                    if (yy < 3) matrix[xx][yy+1].requestFocus();
                }
                // Add the other directions here
            }
        });

        matrix[x][y] = b;
    }

}

但是我如何使用箭头在按钮之间浏览?向上,向下,向左,向右? - Carnal
1
<enter>在您的Java按钮上真的有效吗?我使用addActionListener,只有<space>可以正常工作。为什么我的机器上行为会不同呢? - toto2
1
这是一个LAF问题。在Windows上,按Enter键将激活按钮。在Metal中,您需要使用空格键。 - camickr
@camickr 谢谢。我在使用 Windows,但是我正在使用 Nimbus。 - toto2
1
我不确定人们认为哪里有问题。在我看来,它看起来很好。 - jjnguy

2
请参见按键绑定
component[0][0].getInputMap().put(KeyStroke.getKeyStrokeForEvent(KeyEvent.VK_RIGHT),
                        "moveRight");
component[0][0].getActionMap().put("moveRight", new Action() {
             @Override public void actionPerformed() {
                  component[0][1].requestFocus();
             }
});

我不确定代码是否完全正确,但你可以理解思路。 你需要完成36个这样的操作以获取所有按钮之间的方向, 因此你可能需要编写一些循环来自动化该过程。


+1 给键位绑定;你也许可以按照这里所建议的重新设计映射到按钮创建中。 (https://dev59.com/3G025IYBdhLWcg3wyZEn#5797965) - trashgod

2
我如何通过按下ENTER键而不是点击鼠标来“点击”JButton?
参见 Enter Key and Button
如何使用键盘箭头而不是鼠标浏览JButton
对于右/左箭头键,您可以将这些KeyStrokes添加到焦点遍历键中。请参见如何使用焦点子系统
对于上/下箭头键,您需要创建一个自定义操作,然后将该操作绑定到KeyStroke。请参见如何使用键绑定。教程中还有关于如何使用操作的部分。

1
使用聚焦子系统。
这将让您开始使用箭头键选择组件。它尚未经过测试,敬请谅解:D
假设您在JFrame中拥有按钮数组,
JFrame frame = new JFrame();
//pseudo-method to add your buttons to the frame in the appropraite order.
frame.addButtonsToPanel(buttonArray, frame); 

//gets the default forward traversal keys (tab)
Set forwardKeys = frame.getFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 

// your own set of forward traversal keys
Set newForwardKeys = new HashSet(forwardKeys); 

// add the RIGHT ARROW key 
newForwardKeys.add(KeyStroke.getKeyStroke(
    KeyEvent.VK_RIGHT, 0)); 

//apply your  new set of keys
frame.setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 
    newForwardKeys); 

//gets the default backward traversal keys (shift-tab)
Set backwardKeys = frame.getFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 

// your own set of backward traversal keys
Set newBackwardKeys = new HashSet(backwardKeys); 

// add the LEFT ARROW key 
newBackwardKeys.add(KeyStroke.getKeyStroke(
    KeyEvent.VK_LEFT, 0)); 

//apply your  new set of keys
frame.setFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 
    newBackwardKeys); 

附注:有关更多详细信息,请参见如何使用焦点子系统


是的,现在已经包含原始参考。 - gotomanners

0

最近我已将这个小功能加入我的图形用户界面实用工具类。它只是向同一系统添加新的键,该系统执行 [tab] 焦点更改:

public static void addUpDownToTraversalKeys(Component c)
{   
    addTraversalKeys(c, KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, KeyEvent.VK_DOWN);
    addTraversalKeys(c, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, KeyEvent.VK_UP);
}

public static void addLeftRightToTraversalKeys(Component c)
{   
    addTraversalKeys(c, KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, KeyEvent.VK_RIGHT);
    addTraversalKeys(c, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, KeyEvent.VK_LEFT);
}

public static void addTraversalKeys(Component c, int keysetId, int...keyCodes)
{   
    HashSet<AWTKeyStroke> newKeys = 
        new HashSet<AWTKeyStroke>(
                c.getFocusTraversalKeys(keysetId));
    for (int keyCode : keyCodes)
        newKeys.add(AWTKeyStroke.getAWTKeyStroke(keyCode, 0));
    c.setFocusTraversalKeys(keysetId,newKeys);
}

在我的GuiUtilities类中添加了一个简单的调用:GuiUtilities.addUpDownToTraversalKeys(this);,在框架的构造函数内使用上下箭头键可以浏览所有元素。请注意,如果您有文本区域,则不建议使用addLeftRightToTraversalKeys() ;)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接