0

上个月,我用我对 Java 的了解编写了一个可爱的 Tictactoe 游戏。它的一个组成部分在下面的 3 个代码片段中:

// from the constructor ...
        buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(3, 3));
        guiFrame.add(buttonPanel);//, BorderLayout.CENTER); 
        for (int i = 0; i < 3; i++) 
          for (int j = 0; j < 3; j++) 
            button[i][j] = addButton(buttonPanel, i, j);
// ...

     private JButton addButton (Container parent, int row, int col) {
        int v = (10 * (row + 1) + col + 1); // 11, 12, 13, 21, 22, 23, ... 33
        String s = " " + v;
        JButton cell = new JButton();
        parent.add(cell);
        cell.setActionCommand(s);
        cell.addActionListener(this);
        return cell;
      }  

       public void actionPerformed(ActionEvent e) {
// ... snip
        String r = e.getActionCommand().substring(1, 2);  // row 1, 2, or 3
        String c = e.getActionCommand().substring(2, 3);  // col 1, 2, or 3
        try {
          row = Integer.parseInt(r);      col = Integer.parseInt(c);
        }
        catch (Exception ex) {            }
       }

它的要点是将(行,列)信息存储到每个单元格的“动作命令”中,以便我以后可以getActionCommand用来判断谁的单元格包含 X 或 O(通过未显示的逻辑)。

可能是更好的方法;无论如何,它有效。

现在我要处理一个 11x11 的网格,它或多或少是一个填字游戏网格。我想使用类似的逻辑来确定JTextField刚刚敲击的按键组合以确定是否将背景设置为黑色。这是添加单元格的非常相似的逻辑:

 private JTextField addCell (Container parent, int row, int col) {
    JTextField cell;
    cell = new JTextField();
    int v = (100 * (row + 1) + col + 1);
     // v will go 101,102,...111; 201,202,...,211; ... 1101,1102,...1111
    String s = "" + v;
    cell.setActionCommand(s);
    parent.add(cell);
    cell.addKeyListener(this);
    cell.addActionListener(this);
    return cell;
  }  

但我找不到像听众事件这样getActionCommand的东西。JTextField

这是我从以下System.out.println("keyPressed " + evt.getSource());语句中 得到的内容(为了便于阅读而进行了大量编辑) public void keyPressed(KeyEvent evt)

keyPressed JTextField  
[
 ,  5,  5,  34x32,
 layout =  BasicTextUI$UpdateHandler,
 alignmentX = 0.  0,  alignmentY = 0.  0,
 border =  BorderUIResource$CompoundBorderUIResource@f864fe,
 flags = 296,
 maximumSize = ,  minimumSize = ,  preferredSize = ,
 caretColor = PrintColorUIResource  [r = 51,  g = 51, b = 51],

 disabledTextColor = ColorUIResource  [r = 184, g = 207, b = 229],
 editable = true,
 margin =  InsetsUIResource [top = 0, left = 0, bottom = 0, right = 0],

 selectedTextColor = PrintColorUIResource  [r = 51, g = 51, b = 51],
 selectionColor = ColorUIResource  [r = 184, g = 207, b = 229],
 columns = 0,  columnWidth = 0,  

                                   command = 101,

 horizontalAlignment = LEADING
]

在最后一行旁边吹了,这command = 101正是我需要得到的,但无论如何我尝试过“命令”都不可用。

你的想法/建议/hellllllp?

4

4 回答 4

2

如果您想知道哪个组件生成了事件,您应该使用该事件来获取源:

e.getSource();

动作命令仅适用于 ActionListener(在这种情况下,您将使用 ActionEvent 的 getActionCommand() 方法)而不是 KeyListener。

编辑:

创建一个地图来保存您需要的信息:

Map<Component, Point> textFields = new Hashmap<Component, Point>();

现在在 addCell 方法中,将数据添加到地图中:

textFields.put(cell, new Point(row, col));

然后在 KeyListener 中访问该点:

Point whatever = textFields.get(event.getComponent());

现在您知道输入文本的文本字段的行/列。

或者,正如 MadProgrammer 已经建议的那样,您可以将 Point 添加为每个 JTextfield 的客户端属性。这种方法可能比这个建议要容易一些。但是,该方法将为每个 JTextField 创建一个 Map,并且该方法仅为所有文本字段创建一个 Map,因此效率更高。

于 2013-10-10T20:17:28.237 回答
0

肯定有比这更好的方法:有——在这之前看到答案

  public void keyPressed(KeyEvent evt) { 
    String s = (evt.getComponent().toString());
    StringBuffer cmd = new StringBuffer("0");
    int start = s.indexOf("command") + 8;
    int thru = s.indexOf(',',start);
    cmd.append(s.substring(start,thru));
    if(cmd.length() > 4) 
         s = cmd.substring(1);
    else s = cmd.toString();
    int row = Integer.parseInt(s.substring(0,2));
    int col = Integer.parseInt(s.substring(2,4));
}

但如果没有,我得到了我想要的……虽然丑陋,而且就逻辑而言受到折磨——被疲劳和沮丧折磨。

(嘿——我刚刚发现了“草稿保存”功能——StackOverflow ROCKS!!)

于 2013-10-11T00:05:05.800 回答
0

是的,有更好/不同的方式:

  public Cell commandToCell(String s){
    Cell c = new Cell();
    int start = s.indexOf("command") + 8;
    String s1 = s.substring(start,start+1);
    String s2 = s.substring(start+1,start+2);
    if(s1.charAt(0) == 'A') c.row = 10; else c.row = Integer.parseInt(s1);
    if(s2.charAt(0) == 'A') c.col = 10; else c.col = Integer.parseInt(s2);
    return c;
  }

keyPressed通过调用

Cell cursorCell = commandToCell(evt.getComponent().toString());

请注意,这getSource()并没有告诉我正在处理 11x11 网格的哪个单元格,这就是我使用 setActionCommand 的原因。

于 2013-10-15T22:15:09.277 回答
0

我决定重写这个程序,因为它失控了,真的很垃圾——大量的“受折磨的代码”。

当我到达与上面相同的基本区域时-“我如何知道单击鼠标或在单元格中按下键时哪个网格单元调用了 keyListener?”,我现在使用e.getComponent().getLocation(),它给出了相对于( 0,0),这是包含网格的框架的左上角。

然后我使用线性函数interp来确定 的行和列grid[][]

 private static int interp(int z){
   return (z - 5)*10/400;
 }

这很好用,因为我的 11x11 网格是 440x440 像素。

这段代码在两者中都keyPressed可以mouseClicked 解决问题:

xpix = e.getComponent().getLocation().x;
ypix = e.getComponent().getLocation().y;
setCursor(interp(ypix), interp(xpix));
于 2014-04-24T03:19:08.973 回答