代码之家  ›  专栏  ›  技术社区  ›  DSlomer64

如何从JTextField中“获取ActionCommand”?我在调试时看到了,但是

  •  0
  • DSlomer64  · 技术社区  · 11 年前

    上个月,我用对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(获取操作命令) 对于 文本框 听众的事件。

    以下是我从 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 ,这正是我需要了解的,但“命令”无论如何都不可用。

    你的想法/建议/helllllllp?

    4 回复  |  直到 11 年前
        1
  •  2
  •   camickr    11 年前

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

    e.getSource();
    

    action命令仅用于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,因此效率更高。

        2
  •  0
  •   DSlomer64    11 年前

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

      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的原因。

        3
  •  0
  •   DSlomer64    11 年前

    肯定有比这更好的方法: 有——见前面的答案

      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!!)

        4
  •  0
  •   DSlomer64    10 年前

    我决定重写这个程序,因为它已经失控了,而且真的是垃圾——一大堆“折磨人的代码”。

    当我到达与上面相同的基本区域时——“当鼠标被点击或单元格中的某个键被按下时,我如何知道哪个网格单元格调用了keyListener?”,我现在使用 e.getComponent().getLocation() ,它给出了相对于(0,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));