前几天我问了另一个关于在 swing GUI 中获取键盘输入的问题——实际上是 MCR 输入。一位用户发现了某人编写的低级键盘钩子(Hook)。非常酷,而且它大部分都有效。我必须学习一些新东西来实现它(总是乐于这样做),而且我可能不完全理解发生了什么。
事情是这样的,我将在下面发布代码,当我为键盘钩子(Hook)实现线程时,它现在会通过一个 while 循环(在 CardRead.java 中成功 == false)运行两次。如果我对样本数据进行硬编码,它只会运行一次。如果我删除键盘 Hook 并使用普通的 Scanner.nextLine()(这意味着我必须在控制台中单击以向应用程序提供输入),它只会运行一次。开始一个新的线程与键盘输入的观察者?两次。我不明白为什么,或者如何解决它。只要能准确了解发生了什么,我就会很高兴——如果你们中有人能告诉我如何修复它,我会欣喜若狂。
代码如下:
CardRead.java
public class CardRead {
public static String raw_card_data;
int readcount = 1;
String[] tracks = new String[2];
String[] tracks_final = new String[2];
public static void main()
{
// This doesn't happen until after card is swiped, dunno why.
//GUI.outputArea.setText(GUI.outputArea.getText() + "\n\n Scan card \n");
boolean success = false;
while (success == false)
{
//raw_card_data = "%test?;testing?"; // <-- using this, runs thru once
// using THIS, runs through twice.
// create an event source - reads from stdin
final KB_EventSource evSrc = new KB_EventSource();
// create an observer
final KB_RespHandler respHandler = new KB_RespHandler();
// subscribe the observer to the event source
evSrc.addObserver( respHandler );
// starts the event thread
Thread kb_thread = new Thread(evSrc);
kb_thread.start();
// sleep until card swiped
while (raw_card_data == null)
{
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
System.out.println(raw_card_data);
// Tokenize raw_card_data
StringTokenizer tokenizer = new StringTokenizer(raw_card_data, "?");
int i = 0;
do
{
tracks[i] = tokenizer.nextToken();
System.out.println(i + ": " + tracks[i]);
i++;
}
while (tokenizer.hasMoreTokens());
//System.out.println(track1);
//System.out.println(track2);
tracks_final[0] = tracks[0].substring(1,tracks[0].length());
if (tracks[1] != null)
{
tracks_final[1] = tracks[1].substring(1,tracks[1].length());
}
if ( (readcount <= 5) && ( (tracks_final[0].equals("E") || tracks_final[0].equals(null) ) || (tracks_final[1].equals("E") || tracks_final[1].equals(null)) ) )
{
GUI.notout.setText("Card Read Unsuccessful. Scan Again.");
GUI.outputArea.setText(GUI.outputArea.getText() + "Card read unsuccessful. Scan again. \n");
success = false;
readcount++;
}
else if (readcount <= 5)
{
GUI.notout.setText("Card Successfully Read");
GUI.outputArea.setText(GUI.outputArea.getText() + "\n Success! \n");
GUI.outputArea.setText(GUI.outputArea.getText() + "Track 1 = " + tracks_final[0] + "\n");
GUI.outputArea.setText(GUI.outputArea.getText() + "Track 2 = " + tracks_final[1] + "\n");
success = true;
} // end if else chain
} // end while success == false
} // end public void main
} // end class CardRead
KB_RespHandler.java
import java.util.Observable;
import java.util.Observer;
public class KB_RespHandler implements Observer
{
private String resp;
public void update (Observable obj, Object arg)
{
if (arg instanceof String)
{
resp = (String) arg;
CardRead.raw_card_data = resp;
}
}
}
KB_EventSource.java
import de.ksquared.system.keyboard.*;
import java.util.Observable;
public class KB_EventSource extends Observable implements Runnable
{
public static String temp = "";
public static String output = "";
public void run()
{
new GlobalKeyListener().addKeyListener(new KeyAdapter()
{
@Override public void keyPressed(KeyEvent event)
{
switch(event.getVirtualKeyCode())
{
case KeyEvent.VK_0:
if (event.isShiftPressed() == true)
temp += ")";
else if (event.isShiftPressed() == false)
temp += "0";
break;
case KeyEvent.VK_1:
if (event.isShiftPressed() == true)
temp += "!";
else if (event.isShiftPressed() == false)
temp += "1";
break;
/*insert processing for other keys here*/
case KeyEvent.VK_SPACE:
if (event.isShiftPressed() == true)
temp += " ";
else if (event.isShiftPressed() == false)
temp += " ";
break;
case KeyEvent.VK_RETURN:
/*if (event.isShiftPressed() == true)
temp += "\n";
else if (event.isShiftPressed() == false)
temp += "\n";*/
setChanged();
notifyObservers(temp);
//clearChanged();
break;
} // end switch (event.getVirtualKeyCode())*/
} // end public void keyPressed
});
while(true)
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
所以,我不知道发生了什么。我在想也许我需要在收到输入后停止线程 kb_thread
,但我找不到任何方法来做到这一点。 thread.stop()
和 thread.destroy()
已弃用,Eclipse 和 Google 告诉我不要使用它们。无论如何,这甚至可能不是我需要做的。
最佳答案
“CardRead.java”中的注释说“成功后将更改 success = true”。
这是否意味着它可能会失败,所以它不会改变成功
?
如果这是真的,那么 raw_card_data
仍将是非空的,并且它会重试。
我假设您在某个时候再次将 raw_card_data
重置为 null。
另外一点,这个:
if (event.isShiftPressed() == true)
temp += ")";
else if (event.isShiftPressed() == false)
temp += "0";
可以简化为:
if (event.isShiftPressed())
temp += ")";
else
temp += "0";
关于Java:实现一个新线程,现在我的代码执行了两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8932740/