我上个月使用我对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) { }
}
它的要点是将(row,col)信息存储到每个单元格的“动作命令”中,以便稍后我可以使用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
的{{1}}监听器事件。
以下是JTextField
中System.out.println("keyPressed " + evt.getSource());
语句中的内容(针对可读性进行了大量编辑):
public void keyPressed(KeyEvent evt)
并且 thar她吹,在最后一行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
]
旁边,正是我需要得到的,但是“命令”无论如何我都没有尝试过。
您的想法/建议/ helllllllp?
答案 0 :(得分:2)
如果您想知道哪个组件生成了该事件,您应该使用该事件来获取源:
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:
Point whatever = textFields.get(event.getComponent());
现在您知道输入文本的文本字段的行/列。
或者,正如MadProgrammer已经建议您可以将Point添加为每个JTextfield的客户端属性。这种方法可能比这个建议容易一些。但是,该方法将为每个JTextField创建一个Map,并且此方法仅为所有文本字段创建单个Map,因此它更有效。
答案 1 :(得分:0)
SURELY有一种比这更好的方法: 有 - 看到这个答案
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 !!)
答案 2 :(得分: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的原因。
答案 3 :(得分:0)
我决定改写这个程序,因为它失控并且真的是垃圾 - 大量的&#34;折磨的代码&#34;。
当我到达与上面相同的基本区域时 - &#34;当单击鼠标或在单元格中按下某个键时,如何知道哪个网格单元调用了keyListener?&#34;,我现在使用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));