Topic: 键盘事件问题 急

  Print this page

1.键盘事件问题 急 Copy to clipboard
Posted by: elminsterjimmy
Posted on: 2006-11-01 13:16

我在一个jframe里有一个键盘事件,但当加了个按钮之后这个键盘事件就不能响应了,请问是什么问题。

2.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: bingjiling1636
Posted on: 2006-11-01 22:12

问题是帮我发的,先谢谢LZ
具体问题是,我在一个PANEL里面画图,并用键盘控制其变化,然后当我因需要在新建另一个panel,并放入同一个FRAME后,再在后一个panel里面加入了一个
BUTTON 但是,这时,再运行时突然发现键盘控制无效了。

3.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: guochun
Posted on: 2006-11-03 16:56

应该是第一个PANEL失去焦点了吧

4.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: bingjiling1636
Posted on: 2006-11-03 21:11

哪请问有解决的方法吗?我接触JAVA的图形界面不是很久
有的话,谢谢告诉我

5.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: dejinzhao
Posted on: 2006-11-05 23:02

/** 不要直接向panel中添加键盘事件(add方法)、应该用类似下面的方法
*KeyStroke shiftup = KeyStroke.getKeyStroke(KeyEvent.VK_UP,java.awt.event.InputEvent.SHIFT_DOWN_MASK);
panel.registerKeyboardAction(this,"shiftup",shiftup,JComponent.WHEN_FOCUSED);
*/
//运行结果如图

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;

public class TestJPanel implements java.awt.event.ActionListener{
private JPanel panel;
private Point last;
private java.util.Vector lines;
private static final int SMALL_INCREMENT=4;
private static final int LARGE_INCREMENT=8;
int d=SMALL_INCREMENT;
public TestJPanel() {
last=new Point(100,100);
lines=new java.util.Vector();
JFrame frame=new JFrame();
panel=new JPanel(){
public void paintComponent(Graphics g){
super.paintComponentPresent;
Point pointStart,pointEnd;
g.setColor(java.awt.Color.red);
for(int i=0;i<lines.size()-1;i++){
pointStart=(Point)lines.elementAtLight Bulb;
pointEnd=(Point)lines.elementAt(i+1);
g.drawLine(pointStart.x,pointStart.y,pointEnd.x,pointEnd.y);
}
}
};
panel.setLayout(null);
javax.swing.JButton button=new javax.swing.JButton();
button.setBounds(10,10,100,30);
panel.add(button);//添加按钮
frame.getContentPane().add(panel,java.awt.BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

KeyStroke shiftup = KeyStroke.getKeyStroke(KeyEvent.VK_UP,java.awt.event.InputEvent.SHIFT_DOWN_MASK);
panel.registerKeyboardAction(this,"shiftup",shiftup,JComponent.WHEN_FOCUSED);
KeyStroke shiftdown = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,java.awt.event.InputEvent.SHIFT_MASK);
panel.registerKeyboardAction(this,"shiftdown",shiftdown,JComponent.WHEN_FOCUSED);

KeyStroke up = KeyStroke.getKeyStroke(KeyEvent.VK_UP,0);
panel.registerKeyboardAction(this,"up",up,JComponent.WHEN_FOCUSED);
KeyStroke down = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0);
panel.registerKeyboardAction(this,"down",down,JComponent.WHEN_FOCUSED);
KeyStroke left = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0);
panel.registerKeyboardAction(this,"left",left,JComponent.WHEN_FOCUSED);
KeyStroke right = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0);
panel.registerKeyboardAction(this,"right",right,JComponent.WHEN_FOCUSED);
frame.setBounds(30,30,300,300);
frame.setVisible(true);
}
public void add(int dx, int dy) {
Point end=new Point(last.x+dx,last.y+dy);
lines.add(end);
panel.repaint();
last=end;
}
public static void main (String args[]) {
new TestJPanel();
}
public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
String actionName=actionEvent.getActionCommand();
System.out.println("actionName="+actionName);
if(actionName.equalsIgnoreCase("shiftup")){
d=SMALL_INCREMENT;
}
if(actionName.equalsIgnoreCase("shiftdown")){
d=LARGE_INCREMENT;
}
if(actionName.equalsIgnoreCase("up")){
add(0,-d);
}
if(actionName.equalsIgnoreCase("down")){
add(0,d);
}
if(actionName.equalsIgnoreCase("left")){
add(-d,0);
}
if(actionName.equalsIgnoreCase("right")){
add(d,0);
}
}
}

6.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: dejinzhao
Posted on: 2006-11-06 07:34

上面程序的程序还有缺点、将JComponent.WHEN_FOCUSED该成JComponent.WHEN_IN_FOCUSED_WINDOW回更好!

7.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: liangx
Posted on: 2006-11-09 16:49

哇!这个正是我想了几天的问题,本来想上来问问人的。结果有现成的
娃哈哈!
谢谢dejinzhao.

8.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: dejinzhao
Posted on: 2006-11-10 09:04

没有现成的、是我现写的、你出题、我答题
其实用registerKeyboardAction方法也不好、最好用javax.swing.InputMap
类和javax.swing.ActionMap类、你自己研究研究吧

9.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: liangx
Posted on: 2006-11-10 12:16

我看了javadoc。
registerKeyboardAction()已经是不在被建议使用的方法。文档中建议使用
getInputMap().put(aKeyStroke,aCommand)和getActionMap().put(aCommand,aAction)来组合代替
原方法。以下代码实现了相同的功能。


import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class ActionSample extends AbstractAction {

  
  private final KeyStroke up=KeyStroke.getKeyStroke(KeyEvent.VK_UP,0);
  private final KeyStroke down=KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0);
  public ActionSample() {
    JFrame frame=new JFrame("测试Action");
    JPanel c=(JPanel)frame.getContentPane();
    
    
    c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(up,"up");
    c.getActionMap().put("up",this);
    
    c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(down,"down");
    c.getActionMap().put("down",this);
    frame.setSize(200,200);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    new ActionSample();

  }

  public void actionPerformed(ActionEvent e) {
    System.out.println(e.getActionCommand());
    
  }

}


==

但是问题出来了。在actionPerformed方法中。无法正确打印出actionCommand的结果。这就导致了无法判断到底那一个建被按下了。要解决这个问题的办法是有。例如像JBuilder一样。为每个按键绑定一个匿名Action类但是,我还是想知道actionCommand的传递原理。

10.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: dejinzhao
Posted on: 2006-11-11 00:11

/**
*研究、运行该程序、你可能有所收获
*/

import java.awt.event.*;
import javax.swing.*;

public class ActionSample extends AbstractAction {

private KeyStroke up=KeyStroke.getKeyStroke(KeyEvent.VK_UP,InputEvent.SHIFT_DOWN_MASK);
private KeyStroke down=KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0);
private KeyStroke other=KeyStroke.getKeyStroke(KeyEvent.VK_E,0);
private AbstractAction action;
private Object currentCommand;
private ComponentInputMap inputMap;

public javax.swing.ActionMap actionMap=new javax.swing.ActionMap(){
public javax.swing.Action get(Object key){
return action;
}
};

public ActionSample() {
action=this;
JFrame frame=new JFrame("测试Action");
JPanel c=new JPanel();
frame.getContentPane().add(c,java.awt.BorderLayout.CENTER);
inputMap=new ComponentInputMap(c){
public Object get(javax.swing.KeyStroke keyStroke){
currentCommand=super.get(keyStroke);
return keyStroke;
}
};

c.getInputMap(javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW).setParent(inputMap);
c.getActionMap().setParent(actionMap);

inputMap.put(up,"up");
actionMap.put("up",this);
inputMap.put(down,"down");
actionMap.put("down",this);
inputMap.put(other,"other");
actionMap.put("other",this);
frame.setSize(200,200);
c.requestFocus();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
new ActionSample();
}
public void actionPerformed(ActionEvent e) {
if(currentCommand==null)return;
String s=currentCommand.toString();
if(s.equalsIgnoreCase("up")){
System.out.println("up");
return;
}
if(s.equalsIgnoreCase("down")){
System.out.println("down");
return;
}
if(s.equalsIgnoreCase("other")){
System.out.println("E");
return;
}
System.out.println("other keys");
}
}

11.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: liangx
Posted on: 2006-11-11 17:32

马上拿回去试试。
这2天收获不少阿

12.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: liangx
Posted on: 2006-11-12 15:09

把代码研究了一下。自己做了一些Action和ActionListener的实验,又多了一些理解。不敢独享。
dejinzhao兄的例子是通过一个全局变量来传递,并没有使用原来的action command来传递信息。
只要稍微修改一下我原来的代码就可以实现传递action command的功能。在主类的构造方法中加上

putValue(Action.ACTION_COMMAND_KEY,"action_command");

但是,因为这里使用了主类作为Action对象。因此还是无法区分是哪个事件激发的。至于怎么区分请看我后面的例子。让我们看Action的javadoc,有几个常用属性(我只说1~2个):NAME,ACTION_COMMAND_KEY
我的理解是:Action 一个行动对象,描述了行动的各种属性(包括行动的行为actionPerformed方法),而ActionListener就单纯的只描述了行动的行为(actionPerformed方法)

例如以下的一个实验。为JButton使用setAction方法和用addActionListener方法。得到的效果就完全不同

import java.awt.*;

import javax.swing.*;

/**
* @ActionSample.java
* 2006-11-12
*/

/**
* 例子显示了2个JButton的对象使用了相同的一个Action
* 但是却出现了不同的结果.
*/
public class ActionSample extends JFrame {

  class ActionTest extends AbstractAction{
    ActionTest(){
      putValue(Action.ACTION_COMMAND_KEY,"UseMothedSetAction");
      putValue(Action.NAME,"使用setAction,将会覆盖掉原来的\"Test1\"标题");
    }
    public void actionPerformed(ActionEvent e) {
      System.out.println(e.getActionCommand());
    }
    
  }
  public ActionSample(){
    super("Action例子");
    Action actionTest = new ActionTest();
    JPanel c=(JPanel)getContentPane();
    c.setLayout(new GridLayout(2,1));

    //注意这里.我为btnTest1定义了"Test1"的标题.
    //但是显示出来的结果却不是.
    JButton btnTest1=new JButton("Test1");
    JButton btnTest2=new JButton("Test2");
    btnTest1.setAction(actionTest);
    //这个方法会把actionTest中的action command内容冲
    //掉,用JButton自己的缺省内容代替.
    btnTest2.addActionListener(actionTest);
    c.add(btnTest1);
    c.add(btnTest2);
    
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(400,200);
    setVisible(true);
  }

  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    new ActionSample();

  }

}

==

总结以上,简单的来说(这些都是我个人的理解):
如果组件使用Action来控制行为。我们就必须在Action对象中设置组件的各种属性。
而如果是ActionListener,则有组件自己去设置属性。

13.Re:键盘事件问题 急 [Re: elminsterjimmy] Copy to clipboard
Posted by: lijipeipp
Posted on: 2006-11-14 14:12

搂主的问题我觉得是这样的一个小错误:
后面添加的JPanel把前面的JPanel覆盖了,所以看上去好像是没有得到控制,其实是因为在下面的那个JPanel在画,但上面的JPanel没有画,覆盖了, 建议改一下jframe 的布局管理器。


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923