开发者

Browsing JButtons with Arrow Keys

I've made a JButton array, which represent cards, there are 16 of them, 4 by 4. How can I browse among the JButton with the arrows on keyboar开发者_Go百科d instead of the mouse, and how can I "click" on JButton by pressing ENTER instead of mouseclicking? Maybe there is another way of doing this instead of using JButtons?

Best regards!


I have created a solution that will allow you to navigate buttons with the arrow keys and activate them with space and enter.

Below is all of the code. No comments are provided, so let me know if you have any questions.

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

To run this, simply paste into a class called ButtonPane.

The important bit here is calling requestFocus() on the correct JButton when an arrow key is called. I also registered an extra KeyListener for when the Enter key is pressed.


See key bindings.

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

I am not sure the code is quite right, but you get the idea. You'll have to do 36 of those to get all the directions between all buttons, so you'll probably want to write some loops to automate the process.


Just press Enter on your keyboard... Make sure you use

button.addActionListener(yourActionListener);

instead of creating a mouse listener.

Oh, I forgot the other part. :D

For browsing, you can use button.requestFocus() to change the focus to a specific button.

Here is some sample code:

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

}


how can I "click" on JButton by pressing ENTER instead of mouseclicking?

See Enter Key and Button.

How can I browse among the JButton with the arrows on keyboard instead of the mous

For the right/left arrow keys you can add these KeyStrokes to the focus traversal keys. See How to Use the Focus Subsystem.

For the up/down keys you will need to create a custom Action and then bind the Action to a KeyStroke. See How to Use Key Bindings. There is also a section in the tutorial on How to Use Actions.


Using the Focus Subsystem.

This should get you started on using the arrow keys to select components. It is untested so pardon any errors :D

Assuming you have your button array in a 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); 

p.s See How to Use the Focus Subsystem for more details


I've added this little gem into my GUI utilities class recently. It simply adds new keys to the same system that does the [tab] focus changing:

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

Added to my GuiUtilities class, a simply call to GuiUtilities.addUpDownToTraversalKeys(this); inside the frame's constructor allows using the up and down arrow keys to go through all elements. Note that addLeftRightToTraversalKeys() is not advised if you got text areas ;)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜