我们正在替换最初为MSDOS编写的遗留C应用程序(是的,信不信由你!)。此应用程序使用一个特殊重映射的键盘拦截DOS键盘中断(记住??!)有时会改变用户按下的键的扫描码,以便进行不同的处理。然后在按键上放置特殊标签,告诉用户这些按键的“新”含义。
需要新的Java版本来保留目标用户群非常熟悉的键盘布局。
我们尝试做的一个例子如下:
您可能从未想过这一点,但现代电话的数字键盘与计算机键盘的数字键盘相反。前者1-2-3位于顶行,后者位于底行。我们需要使键盘的数字键盘看起来像电话。假设当用户在数字键盘上输入“7”时,我们希望它看起来好像输入“1”,当他输入“8”时,我们想要一个“2”,当他输入“3”时我们想要一个“9”。
我们还需要做更多的事情来模拟DOS应用程序,但我们现在甚至无法解决这个简单的案例。我已经遍布Key Binding,KeyAdapters,KeyListeners,甚至KeyEventDispatcher,我无法做到这一点。我很确定我们必须在Java允许的最低级别上工作,以尽可能接近遗留应用程序的工作。不用说,我们希望最干净的实现成为可能,这样应用程序级代码就不会被inputMaps和actionMaps等所占用。尽可能地需要全局处理。有人可以帮忙吗?
答案 0 :(得分:3)
如果我这样做,我会编写Java App而不必担心密钥绑定。假设当组件获得#7#7的键事件时,不要担心7或1是否真的被键入。应用程序不应该关心如何在键盘上映射键。这应该可以让您立即开始开发应用程序。
就重写键绑定而言,这似乎就像你想看的那样:http://download.oracle.com/javase/7/docs/api/java/awt/KeyEventDispatcher.html
听起来您可以编写自己的KeyEventDispatcher来处理所有键映射逻辑,它可以防止映射逻辑弄乱应用程序中的其余逻辑。
答案 1 :(得分:2)
这很hacky,我承认我自己没有使用它,但你可以继承KeyEvent
并根据需要覆盖这些字段。因此yourSubclass.VK_NUMPAD1
是KeyEvent.VK_NUMPAD7
的整数值,yourSubclass.VK_NUMPAD2
是KeyEvent.VK_NUMPAD8
的整数值,等等。然后在通常使用KeyEvent
的地方使用您的子类。
答案 2 :(得分:2)
我也同意KeyEventDispatcher应该可以工作。但如果这是一个版本/平台问题,那么也许您可以使用自定义事件队列。见Global Event Dispatching
答案 3 :(得分:1)
我的筹码溢出! 答案在这里: http://download.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html 其中说:
按下按键并释放按键 事件,getKeyCode方法返回 事件的keyCode。对于键入键 事件,getKeyCode方法总是如此 返回VK_UNDEFINED。
我最初的尝试认为它可以在KEY_TYPED上获得keyCode。它不能,并且KEY_TYPED事件破坏了在KEY_PRESSED中完成的映射。
这是一个有效的实施方案:
import static java.awt.event.KeyEvent.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class KeyboardDispatcherDemo extends JFrame {
/**
* This class shows how to map numeric keypad keys.
* It performs two conversions:
* 1. lower-to-uppercase
* 2. if numeric keypad 7-9 is typed, 1-3 appears and vice versa.
*
* This is modified from the code at
* http://www.exampledepot.com/egs/java.awt/DispatchKey.html#comment-51807
* which demoes the lower-to-upper conversion.
*
* It doesn't yet handle modified numeric keypad keys.
*
*/
public KeyboardDispatcherDemo() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
new KeyEventDispatcher() {
private char lastMappedKey;
private final Map<Integer, Character> keyMap =
new HashMap<Integer, Character>() {
{
put(VK_NUMPAD1, '7');
put(VK_NUMPAD2, '8');
put(VK_NUMPAD3, '9');
put(VK_NUMPAD7, '1');
put(VK_NUMPAD8, '2');
put(VK_NUMPAD9, '3');
}};
public boolean dispatchKeyEvent(KeyEvent e) {
System.out.println(String.format("INPUT: %s", e.toString()));
boolean dispatch = false;
switch (e.getID()) {
case KeyEvent.KEY_PRESSED:
dispatch = dispatchKeyPressed(e);
break;
case KeyEvent.KEY_TYPED:
dispatch = dispatchKeyTyped(e);
break;
case KeyEvent.KEY_RELEASED:
dispatch = dispatchKeyReleased(e);
break;
default:
throw new IllegalArgumentException();
}
System.out.println(String.format("OUTPUT: %s", e.toString()));
System.out.println();
return dispatch;
}
private boolean dispatchKeyPressed(KeyEvent e) {
char k = e.getKeyChar();
if (k != CHAR_UNDEFINED) {
if (Character.isLetter(k)) {
e.setKeyChar(Character.toUpperCase(e.getKeyChar()));
} else if (e.getModifiers() == 0){
Character mapping = keyMap.get(e.getKeyCode());
if (mapping != null) {
e.setKeyChar(mapping);
}
}
// save the last mapping so that KEY_TYPED can use it.
// note we don't do this for modifier keys.
this.lastMappedKey = e.getKeyChar();
}
return false;
}
// KEY_TYPED events don't have keyCodes so we rely on the
// lastMappedKey that was saved on KeyPressed.
private boolean dispatchKeyTyped(KeyEvent e) {
char k = e.getKeyChar();
if (k != CHAR_UNDEFINED) {
e.setKeyChar(lastMappedKey);
}
return false;
}
private boolean dispatchKeyReleased(KeyEvent e) {
char k = e.getKeyChar();
if (k != CHAR_UNDEFINED) {
e.setKeyChar(lastMappedKey);
this.lastMappedKey=CHAR_UNDEFINED;
}
return false;
}
});
setTitle("KeyboardDispatcherDemo");
JPanel panel = new JPanel();
panel.setBackground(new Color(204, 153, 255));
panel.setLayout(new BorderLayout());
getContentPane().add(panel, BorderLayout.CENTER);
JTextArea staticText = new JTextArea();
staticText.setText("This demonstrates how to map numeric keypad keys. It uppercases all letters and converts Numeric Keypad 1-3 to 7-9 and vice versa. Try it.");
staticText.setLineWrap(true);
staticText.setWrapStyleWord(true);
panel.add(staticText, BorderLayout.NORTH);
staticText.setFocusable(false);
JTextField textField = new JTextField();
textField.setText("");
textField.setHorizontalAlignment(SwingConstants.LEFT);
panel.add(textField, BorderLayout.SOUTH);
textField.setColumns(10);
textField.setFocusable(true);
setSize(getPreferredSize());
setVisible(true);
}
/**
* @param args
*/
public static void main(String[] args) {
new KeyboardDispatcherDemo();
}
@Override
public Dimension getPreferredSize() {
// TODO Auto-generated method stub
return new Dimension(400,300);
}
}
感谢所有推动我回答问题的人。
这让我想到了下一个问题......敬请期待。