关于JPanel响应键盘事件的问题!高分求解!在线等待

时间:2021-12-11 22:10:17

在写一个俄罗斯方块游戏,JPanel游戏面板键盘监听不知哪里出了错,一直没有响应,下面是我的代码,各位大哥给小弟看一看,先在这里谢谢各位了!

class jframe extends JFrame
{   
     public static JPanel gamecanvas,nextcanvas; 
setVisible();

gamecanvas.addKeyListener(new control());
gamecanvas.requestFocus();
}
class control
{
control()//为gamecanvas1.addKeyListener(new control());创建实例对象
{
}
int control(int currentbutton)//这是另一构造函数
{
……
}
public void keyPressed(KeyEvent e)

       if(B.isgameplay) 
     {  
        switch(e.getKeyCode())
      { 
    case KeyEvent.VK_UP:B.turnblock();break; 
          case KeyEvent.VK_DOWN:B.blockdown();break; 
          case KeyEvent.VK_LEFT:B.moveleft();break; 
          case KeyEvent.VK_RIGHT:B.moveright();break; 
         } 
     }
     else return;
      } 
   public void keyTyped(KeyEvent e)
   {
   }
   public void keyReleased(KeyEvent e)
   {
   } 
}

游戏面板在jframe中创建,注册了键盘监听器,键盘监听事件在另一个类control中处理,改来改去也不知道哪里出错,跪求各位大哥帮忙啊!!!!!!!
几天的BUG,非常急,在线等待,快来人啊

45 个解决方案

#1


class control implements KeyListener

#2


坐等高手

#3


这个没做过,帮你顶一下

#4


看了你的source,觉得编译都不会过的

#5


我只把代码复制了一部分,控制类实现了KeyListene接口,另外,这个程序其他没有错误,已经能够运行,就差键盘不能控制,看了不少资料,一直没有解决问题。哪位大哥,来救救我啊!!!!!!

#6


话说,你implements了KeyListener了没

#7


问题补充,JPanel对象的创建我是放在窗体类的,接口实现放在了控制类,向左向右向下的操作方法放在的方块类

#8


引用 5 楼 tengfeng05 的回复:
我只把代码复制了一部分,控制类实现了KeyListene接口,另外,这个程序其他没有错误,已经能够运行,就差键盘不能控制,看了不少资料,一直没有解决问题。哪位大哥,来救救我啊!!!!!!
实现了,我只帖了部分代码

#9


引用 6 楼 luciferdevil 的回复:
话说,你implements了KeyListener了没
晕,点错。实现了,我只贴了部分代码。我看有些人资料说JPanel不能获取焦点,我试了N种方法,程序并不报错,就是和没加键盘事件一样

#10


引用楼主 tengfeng05 的回复:
在写一个俄罗斯方块游戏,JPanel游戏面板键盘监听不知哪里出了错,一直没有响应,下面是我的代码,各位大哥给小弟看一看,先在这里谢谢各位了!

class jframe extends JFrame
{  
  public static JPanel gamecanvas,nextcanvas; 
setVisible();

gamecanvas.addKeyListener(n……


1楼就回你了,你没包含KeyListener接口

#11


private class MyPanel extends javax.swing.JPanel{
        MyPanel(){
            enableEvents(AWTEvent.MOUSE_EVENT_MASK);
            enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
            enableEvents(AWTEvent.KEY_EVENT_MASK); 
        }
        protected void processEvent(AWTEvent e) {
            //添加你自己的事件处理代码
            switch(e.getID()){
            case KeyEvent.KEY_TYPED:

case KeyEvent.KEY_PRESSED:
        }
    };

#12


无论哪个控件、想接受键盘事件、必须先获得“焦点”
panel.requestFocus() ;

#13


引用 12 楼 dejinzhao 的回复:
无论哪个控件、想接受键盘事件、必须先获得“焦点”
panel.requestFocus() ;
我的JPanel对象是在窗体类中定义的,我不想让它作为一个单独的类,接口实现是在控制类中,你的代码是要将JPanel分出来单独作为一个类?另外,我设置焦点了,requestFocus(),setFocusabel()各种方法都用过,无效

#14


实现了KeyListener的话,加句
gamecanvas.setFocusable(true);

应该就行了

#15


你要是非用Jpanel的话,可以自己实现个Jpanel,包含KeyListener接口,然后把Jpanel作为监听器注册给JFrame:
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class KeyListenerTestPanel extends JPanel implements KeyListener {
JLabel Jb;
public KeyListenerTestPanel(){
Jb=new JLabel("测试");
this.add(Jb);
}

public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();

        switch (keyCode) {//判断键盘值

case 37:
Jb.setText("左");
System.out.println("左");
break;// 左
case 38:
Jb.setText("上");
System.out.println("上");
break;// 上
case 39:
Jb.setText("右");
System.out.println("右");
break;// 右
case 40:
Jb.setText("下");
System.out.println("下");
break;// 下

}
}

public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}

public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}
public static void main(String args[]){

JFrame jf = new JFrame();
jf.setSize(100, 100);
KeyListenerTestPanel  jp = new KeyListenerTestPanel();
jf.add(jp);
jf.addKeyListener(jp);
jf.setVisible(true);

}
}

#16


或者直接给JFrame注册监听事件
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class KeyListenerTest extends JFrame implements KeyListener {

JPanel gamecanvas;
JLabel Jb;
public KeyListenerTest(){
Jb=new JLabel("测试");
gamecanvas =new JPanel();
this.setSize(100, 100);
this.addKeyListener(this);
gamecanvas.add(Jb);
this.add(gamecanvas);
this.setVisible(true);

}


public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();

        switch (keyCode) {//判断键盘值

case 37:
Jb.setText("左");
System.out.println("左");
break;// 左
case 38:
Jb.setText("上");
System.out.println("上");
break;// 上
case 39:
Jb.setText("右");
System.out.println("右");
break;// 右
case 40:
Jb.setText("下");
System.out.println("下");
break;// 下

}

}

public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}

public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}

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

}
}

#17


引用 13 楼 tengfeng05 的回复:
我的JPanel对象是在窗体类中定义的,我不想让它作为一个单独的类,接口实现是在控制类中,你的代码是要将JPanel分出来单独作为一个类?另外,我设置焦点了,requestFocus(),setFocusabel()各种方法都用过,无效


我觉得你需要把你的布局晾出来了,setFocusable之后,就可以响应键盘了(已验证)
你现在无法获得事件,应该是被某些控件完全覆盖,因而获得不了焦点,或者被某些控件把键盘事件抢去,或者其它啥

#18


引用 16 楼 werosh 的回复:
或者直接给JFrame注册监听事件

Java code
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel……
感谢风动大地!看了你的代码,你是建议我把JPanel单独作为一个类吗?或者在窗体类中实现KeyListener事件?我是想在控制类中实现键盘事件,JPanel不作为一个单独类,这样有办法吗?

#19


引用 17 楼 truediego 的回复:
引用 13 楼 tengfeng05 的回复:
我的JPanel对象是在窗体类中定义的,我不想让它作为一个单独的类,接口实现是在控制类中,你的代码是要将JPanel分出来单独作为一个类?另外,我设置焦点了,requestFocus(),setFocusabel()各种方法都用过,无效


我觉得你需要把你的布局晾出来了,setFocusable之后,就可以响应键盘了(已验证)
你现在无法……
我的布局是NULL

#20


引用 19 楼 tengfeng05 的回复:
我的布局是NULL

我的意思是你的gamecanvas上面放了什么东西,是不是覆盖满了之类的

下面是我写的一个简单的例子,是可以的,你可以对照你的,看看有没有啥关键的区别
package to.shin.sai;

import java.awt.Container;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test4OutputScreen2Image extends JFrame {
/**
 * 
 */
private static final long serialVersionUID = 1L;

public static void main(String arg[]) {
new Test4OutputScreen2Image();
}

public Test4OutputScreen2Image() {
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Container contentPane = getContentPane();

JPanel keyPanel = new JPanel();
contentPane.add(keyPanel);

JLabel lbl = new JLabel();
lbl.setText("Hello");
keyPanel.add(lbl);

keyPanel.setFocusable(true);
keyPanel.addKeyListener(new controller());

setVisible(true);
}

private class controller implements KeyListener {

@Override
public void keyPressed(KeyEvent keyevent) {
System.out.println(keyevent.getKeyChar());
}

@Override
public void keyReleased(KeyEvent keyevent) {
// TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent keyevent) {
// TODO Auto-generated method stub

}

}

}

#21


很简单的,两个问题。
1.面板implements KeyListener;
2.JPanel上添加其他控件以后,被遮挡的部分是监听不到事件的,要在控件上添加KeyListener。

#22


引用 20 楼 truediego 的回复:
引用 19 楼 tengfeng05 的回复:
我的布局是NULL
我的意思是你的gamecanvas上面放了什么东西,是不是覆盖满了之类的

下面是我写的一个简单的例子,是可以的,你可以对照你的,看看有没有啥关键的区别

Java code
package to.shin.sai;

import java.awt.Container;
import java.awt.eve……

我的JPanel上什么也没有,就是充当画布,在上面画图。然后用键盘对图形进行控制,但是没效

#23


那还是建议你吧JPanel单独做个类吧,这样能把对JPanel操作完全封装到这个类里,其他地方用的时候直接new一下就成了。而且你做画布也要用到JPanel 的 Graphics。

#24


那就采用极端做法
1.在Keypressed里面加System.out
2.把不相关source全注掉,然后一段一段,一句一句释放,看效果

#25


引用 16 楼 werosh 的回复:
或者直接给JFrame注册监听事件

Java code
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel……

我照着你的改了,还是没用。很奇怪,你上面的代码结构和我完全是一样,除了一点,我把main方法放在控制类中,但是我的为什么就不起作用呢?我的JPanel对象就是个空面板,只在上面画图·······

#26


main放哪没什么关系吧,代码发来看看。

#27


import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import java.net.*;
class jframe extends JFrame
{   
public static Canvas gamecanvas1,nextcanvas;
JPanel messagepanel;
JMenuBar mymenubar;
JMenu menu1,menu2,menu3,menu4;
  public static JMenuItem menu1_item1,menu1_item2,menu1_item3,
menu2_item1,
menu3_item1,menu3_item2,
  menu4_item1,menu4_item2,menu4_item3,menu4_item4,menu4_item5,
menu4_item6,menu4_item7,menu4_item8,menu4_item9,menu4_item10;
public static JButton startbutton,toolbutton1,toolbutton2,toolbutton3,toolbutton4;
  JLabel nextlabel,toollabel1,userscore1,userscore2;
  public static JTextField tooltext1,tooltext2,tooltext3,tooltext4,scoretext1,scoretext2,timetext;
public static JTextArea linkmessagetextarea;
  //取得内容面板
 jframe()  
  {
//窗体//
super("俄罗斯方块");
setSize(535,580);
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}});

//addKeyListener(new control());  
mymenubar=new JMenuBar();//创建菜单栏
gamecanvas1=new Canvas();//创建本机用户面板
messagepanel=new JPanel();//创建信息显示面板
//创建网络用户面板gamecanvas2=new gamecanvas();

Container con=getContentPane();
con.setLayout(null);//设置内容面板的布局模式为空布局
con.add(mymenubar);con.add(gamecanvas1);con.add(messagepanel);// con.add(gamecanvas2);
mymenubar.setBounds(0,0,535,20);
gamecanvas1.setBounds(15,35,300,500);
  messagepanel.setBounds(320,35,200,500);
  // gamecanvas2.setBounds(int x,int y,int a,int b);
  gamecanvas1.setBackground(Color.white);
messagepanel.setBackground(Color.lightGray);

//菜单栏//
menu1=new JMenu("游戏");
menu2=new JMenu("设置");
  menu3=new JMenu("帮助");
  menu4=new JMenu("关卡选择");
mymenubar.add(menu1);mymenubar.add(menu2);mymenubar.add(menu3);
menu1_item1=new JMenuItem("新游戏");menu1_item1.addActionListener(new control(1));
  menu1_item2=new JMenuItem("网络对战");menu1_item2.addActionListener(new control(2));
menu1_item3=new JMenuItem("退出");menu1_item3.addActionListener(new control(3));
menu2_item1=new JMenuItem("背景音乐");menu2_item1.addActionListener(new control(4));
menu3_item1=new JMenuItem("操作方法");menu3_item1.addActionListener(new control(5));
menu3_item2=new JMenuItem("关于···");menu3_item2.addActionListener(new control(6));
  menu4_item1=new JMenuItem("第一关");menu4_item1.addActionListener(new control(7));
menu4_item2=new JMenuItem("第二关");menu4_item2.addActionListener(new control(8));
  menu4_item3=new JMenuItem("第三关");menu4_item3.addActionListener(new control(9));
  menu4_item4=new JMenuItem("第四关");menu4_item4.addActionListener(new control(10));
  menu4_item5=new JMenuItem("第五关");menu4_item5.addActionListener(new control(11));
  menu4_item6=new JMenuItem("第六关");menu4_item6.addActionListener(new control(12));
  menu4_item7=new JMenuItem("第七关");menu4_item7.addActionListener(new control(13));
  menu4_item8=new JMenuItem("第八关");menu4_item8.addActionListener(new control(14));
menu4_item9=new JMenuItem("第九关");menu4_item9.addActionListener(new control(15));
menu4_item10=new JMenuItem("第十关");menu4_item10.addActionListener(new control(16));
menu1.add(menu1_item1); menu1.add(menu1_item2);menu1.add(menu1_item3);
menu2.add(menu2_item1); menu2.add(menu4);
menu3.add(menu3_item1); menu3.add(menu3_item2);
menu4.add(menu4_item1); menu4.add(menu4_item2);
  menu4.add(menu4_item3); menu4.add(menu4_item4);
  menu4.add(menu4_item5); menu4.add(menu4_item6);
  menu4.add(menu4_item7); menu4.add(menu4_item8);
  menu4.add(menu4_item9); menu4.add(menu4_item10);

  //创建NEXT信息子面板
  startbutton=new JButton("开始游戏");startbutton.addActionListener(new control(17));
nextlabel=new JLabel("NEXT");
nextcanvas=new Canvas();   
nextcanvas.setBackground(Color.white);

//创建道具信息子面板
toollabel1=new JLabel("道具");
toolbutton1=new JButton();toolbutton1.addActionListener(new control(18));
tooltext1=new JTextField("x 0",4);
toolbutton2=new JButton();toolbutton2.addActionListener(new control(19));
tooltext2=new JTextField("x 0",4);
toolbutton3=new JButton();toolbutton3.addActionListener(new control(20));
tooltext3=new JTextField("x 0",4);
toolbutton4=new JButton();toolbutton4.addActionListener(new control(21));
tooltext4=new JTextField("x 0",4);

//创建分数显示面板
  userscore1=new JLabel("分数");
  userscore2=new JLabel("对方分数");
scoretext1=new JTextField(6);
scoretext2=new JTextField(6);
timetext=new JTextField ("00:00:00",8);
linkmessagetextarea=new JTextArea("无连接",2,30);

//将NEXT信息子面板和道具信息子面板分数信息子面板添加到信息面板
messagepanel.setLayout(null);
messagepanel.add(startbutton);
messagepanel.add(nextlabel);
messagepanel.add(nextcanvas);
messagepanel.add(toollabel1);
  messagepanel.add(toolbutton1);messagepanel.add(tooltext1);
  messagepanel.add(toolbutton2);messagepanel.add(tooltext2);
messagepanel.add(toolbutton3);messagepanel.add(tooltext3);
messagepanel.add(toolbutton4);messagepanel.add(tooltext4);
messagepanel.add(userscore1);messagepanel.add(userscore2);
  messagepanel.add(scoretext1);messagepanel.add(scoretext2);
messagepanel.add(timetext);
messagepanel.add(linkmessagetextarea);
  
  startbutton.setBounds(60,15,80,30);
nextlabel.setBounds(87,55,40,20);
  nextcanvas.setBounds(63,85,75,90);

toollabel1.setBounds(88,190,40,20);
  toolbutton1.setBounds(10,220,40,40);tooltext1.setBounds(55,220,40,40);
  toolbutton2.setBounds(105,220,40,40);tooltext2.setBounds(150,220,40,40);
toolbutton3.setBounds(10,270,40,40);tooltext3.setBounds(55,270,40,40);
  toolbutton4.setBounds(105,270,40,40);tooltext4.setBounds(150,270,40,40);

userscore1.setBounds(45,325,60,20);userscore2.setBounds(115,325,60,20);
scoretext1.setBounds(25,355,63,30);scoretext2.setBounds(110,355,63,30);
timetext.setBounds(35,395,130,30);
linkmessagetextarea.setBounds(5,435,190,60);
   
setResizable(false);
  setVisible(true);
  gamecanvas1.setFocusable(true);
  gamecanvas1.addKeyListener(new control());
   }
}

#28


class block
{
  int row,col; //记录方块矩阵左上角在gamearea数组中的坐标
  int x,y;
  int blocktype,nexttype;//用来存储七种形态的方块
  int turntype;//用来存储方块的翻转状态
  int isblockdown;//用来记录游戏区底部堆积的方块行数
  int line;//记录可消去的行数
  static boolean isgameplay;
  Color color,nextcolor;
  Graphics g;
  int gamearea[][]=new int[29][15];
    
  int Block[][][][]=
{{{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}},
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}},   
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,1,1,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},
{{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},
{{1,0,0,0}, {1,0,0,0},{1,1,0,0},{0,0,0,0}}},

{{{0,1,1,0},{0,0,1,0},{0,0,1,0},{0,0,0,0}},
{{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}},
{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,1,0,0},{0,1,1,0},{0,0,1,0},{0,0,0,0}},
{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,1,0},{0,0,1,0},{0,0,0,0}},
{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,0,1,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,0,1,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}},

{{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
{{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}}};
//构造方法
block()
{
  blocktype=0;
  turntype=0;
  isblockdown=0;
  isgameplay=false;
   
}
//初始化游戏区域
public void initgamearea()
{
  for(int i=0;i<=24;i++)
  for(int j=0;j<=14;j++)
gamearea[i][j]=0;
  getblock();
}
//产生随机颜色
  public Color randomcolor()  
{   
Color C=new Color((new Double(Math.random() * 128)).intValue() + 128, (new Double(Math.random() * 128)).intValue() + 128, (new Double(Math.random() * 128)).intValue() + 128);  
return C;
  }
 //画NEXT方块
 public void drawnext(int nexttype,Color nextcolor)
 {
   g=jframe.nextcanvas.getGraphics();
   g.clearRect(0,0,65,90);
   g.setColor(nextcolor);
   switch(nexttype)
   {
     case 1:g.fill3DRect(27,5,20,20,true);
        g.fill3DRect(27,25,20,20,true);
g.fill3DRect(27,45,20,20,true);
g.fill3DRect(27,65,20,20,true);break;
     case 2:g.fill3DRect(17,15,20,20,true);
        g.fill3DRect(37,15,20,20,true);
g.fill3DRect(17,35,20,20,true);
g.fill3DRect(17,55,20,20,true);break;
 case 3:g.fill3DRect(17,15,20,20,true);
        g.fill3DRect(37,15,20,20,true);
g.fill3DRect(37,35,20,20,true);
g.fill3DRect(37,55,20,20,true);break;
 case 4:g.fill3DRect(17,15,20,20,true);
        g.fill3DRect(17,35,20,20,true);
g.fill3DRect(37,35,20,20,true);
g.fill3DRect(37,55,20,20,true);break;
 case 5:g.fill3DRect(37,15,20,20,true);
g.fill3DRect(37,35,20,20,true);
g.fill3DRect(17,35,20,20,true);
        g.fill3DRect(17,55,20,20,true);break;
 case 6:g.fill3DRect(17,25,20,20,true);
        g.fill3DRect(37,25,20,20,true);
g.fill3DRect(17,45,20,20,true);
g.fill3DRect(37,45,20,20,true);break;
 case 7:g.fill3DRect(27,25,20,20,true);
        g.fill3DRect(7,45,20,20,true);
g.fill3DRect(27,45,20,20,true);
g.fill3DRect(47,45,20,20,true);break;
    }
 }
//画方块方法
 public void drawblock(int draw)
  {  
   int line1=0,line2=0;
   g=jframe.gamecanvas1.getGraphics();
   g.setColor(color);
   switch(draw)
   {
    case 1: for(int i=0;i<=3;i++)
            for(int j=0;j<=3;j++)
            if(Block[blocktype][turntype][i][j]==1)
            g.fill3DRect((col+j)*20,(row+i)*20,20,20,true);
    case 2: for(int i=0;i<=3;i++)
            for(int j=0;j<=3;j++)
            if(Block[blocktype][turntype][i][j]==1)
              gamearea[row+i][col+j]=draw;
}
  }
  //刷新下落方块方法
  public void updateblock()
  {
    g=jframe.gamecanvas1.getGraphics();
g.setColor(Color.white);
for(int i=0;i<=3;i++)
    for(int j=0;j<=3;j++)
    if(Block[blocktype][turntype][i][j]==1)
    g.fillRect((col+j)*20,(row+i)*20,20,20);
  }
//消行方法
  public void deleteline()
  {
    int temp_line=0,i,j;
    g=jframe.gamecanvas1.getGraphics();
for(i=row;i<=row+4;i++)
  {
    if(temp_line==15) 
  {
    g.copyArea(0,0,300,(i-2)*20,0,20);
line++;
      }  
  for(j=0,temp_line=0;j<=14;j++)
    if(gamearea[i][j]==2) temp_line++;
  jframe.scoretext1.setText(Integer.toString((50+line*50)*line));
  }
  }
//初始化并得到新方块
  public void getblock()
  {  
row=0;
col=6;
isblockdown=0;
turntype=0;
blocktype=(int)(Math.random()*1000)%7;
color=randomcolor();
drawblock(1);
nexttype=(int)(Math.random()*1000)%7;
nextcolor=randomcolor();
drawnext(nexttype,nextcolor);
  }
  //得到下一个方块
  public void getnext()
  {
row=0;
col=6;
isblockdown=0;
turntype=0;
blocktype=nexttype;
color=nextcolor;
drawblock(1);
nexttype=(int)(Math.random()*1000)%7;
nextcolor=randomcolor();
drawnext(nexttype,nextcolor);
  }
//方块旋转方法
  public void turnblock()
  {  
if(moveable('T'))
{
updateblock();
if(turntype==3)
turntype=0;
else
turntype++;
drawblock(1);
}
  }
//方块右移方法
  public void moveright()
  {
if(moveable('R'))
{  
updateblock();
col++;
drawblock(1);
}
  }
//方块左移方法
  public void moveleft()
  {
if(moveable('L'))
{
updateblock();
col--;
drawblock(1);
}
  }
//方块下落方法
  public void blockdown()
  {
if(moveable('D'))
{
updateblock();  
row++;
drawblock(1);
}
else  
{
  drawblock(2);
  deleteline();
  isblockdown=1;
}
  }

//判断方块是否还能移动方法
  public boolean moveable(char direction)
  {
switch(direction)
{
case 'R':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(col+j>=14||gamearea[row+i][col+j+1]==2))
         return false;break;
case 'L':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(col+j<=0||gamearea[row+i][col+j-1]==2))
         return false;break;
case 'D':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(row+i>=24||gamearea[row+i+1][col+j]==2))
         return false;break;
case 'T':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(col+j<=0||col+j>=14||row+i>=24||gamearea[row+i+1][col+j]==2||gamearea[row+i][col+j+1]==2||gamearea[row+i][col+j-1]==2))
         return false;break;
}  
return true;
  }  
 //判断游戏是否结束方法
public boolean isgameplay()
{
  if(gamearea[2][6]==2||gamearea[2][7]==2||gamearea[2][8]==2||gamearea[2][9]==2)
      return false;
  return true;
}
  //定时线程
  public class thread extends Thread
  {
public void run()
{  
while(isgameplay())
{
try{
sleep(control.time);
}catch(InterruptedException e){ }
  if(isblockdown==0)  
blockdown();
if(isblockdown==1)
getnext();
}
}  
  }
//返回内部类thread的引用实例
  public thread th()
  {
    return new thread();
  }   
}

#29


public class control implements ActionListener,KeyListener
{   
  static int time;
  block B;
  int currentbutton;
  //构造方法,为gamecanvas1添加键盘处理事件
  control()
  {
  }
  //构造方法,接受localuser类传递过来int型参数
control(int button)
{
  currentbutton=button;
  time=500;
  B=new block();
}  
  public void actionPerformed(ActionEvent e)
  {
switch(currentbutton)
{
case 1:B.initgamearea();
       B.th().start();
   time().start();break;
case 2:System.exit(0);break;
case 3:System.exit(0);break;
case 4:System.exit(0);break;
case 5:System.exit(0);break;
case 6:System.exit(0);break;
case 7:time=800;break;
case 8:time=750;break;
case 9:time=700;break;
case 10:time=625;break;
case 11:time=550;break;
case 12:time=475;break;
case 13:time=375;break;
case 14:time=275;break;
case 15:time=175;break;
  case 16:time=75;break;
case 17:if(!B.isgameplay)
{  
  
  B.isgameplay=true;
  B.initgamearea();
  B.th().start();
  time().start();
}
else  
{
try
{
  B.th().wait();
}catch(InterruptedException E){}
B.isgameplay=false;

break;
case 18:System.exit(0);break;
case 19:System.exit(0);break;
case 20:System.exit(0);break;
case 21:System.exit(0);break;
default:return;
}
  }

  public void keyPressed(KeyEvent e)
{  
  if(B.isgameplay)  
  {   
  switch(e.getKeyCode())
   {  
  case KeyEvent.VK_UP:System.out.println(0);break; 
  case KeyEvent.VK_DOWN:B.blockdown();break;  
  case KeyEvent.VK_LEFT:B.moveleft();break;  
  case KeyEvent.VK_RIGHT:B.moveright();break;  
  default:return;//用户按错键时结束方法
   }
  }
  return;
 }  
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
  
  public class gametime extends Thread
{  
  SimpleDateFormat starttimeformat= new SimpleDateFormat("HH:mm:ss");
      Date starttime = new Date();
  public void run()
  {
while(B.isgameplay())
    {  
 //B.time();
      try
 {
   sleep(1000);
     }catch(InterruptedException e){ }
  Date nowtime=new Date();
  Date time=new Date(nowtime.getTime()-starttime.getTime()-28800000);
          jframe.timetext.setText(starttimeformat.format(time));
     }
   }
  }
public gametime time()
{
   return new gametime();
}
  public static void main(String args[])
  {
    jframe frame=new jframe();
  }
}

#30


   setResizable(false);
      setVisible(true);
      gamecanvas1.setFocusable(true);
       gamecanvas1.addKeyListener(new control());
这句不对,你吧KeyListener添到panel上了,那个确实监听不到,换成this.addKeyListener看看

还有,你实例化太多监听器了,效率肯定不成,这些完全可以只new一个control

#31


setResizable(false);
  setVisible(true);
   this.addKeyListener(new control());

#32


引用 30 楼 werosh 的回复:
setResizable(false);
  setVisible(true);
  gamecanvas1.setFocusable(true);
  gamecanvas1.addKeyListener(new control());
这句不对,你吧KeyListener添到panel上了,那个确实监听不到,换成this.addKeyListener看看

还有,你实例化太多监听器……
照你说的试了,还是不行。另外,如果不new control(int)的话,怎么像它传递参数?

#33


你的button抢走了你的key事件
点了button之后,要把focus设回给你的gamecanvas

#34


引用 33 楼 truediego 的回复:
你的button抢走了你的key事件
点了button之后,要把focus设回给你的gamecanvas
这样我试过了,如果是向gamecanvas1注册的监听器,点了button后将focus设回来会发生exception,nullpointexception。如果是像jframe注册监听器,点了button后设回来仍旧没有反应,

#35


那是因为你没有初始化B啊,所以才NullPoint的

control() {
B = new block(); //没有这句
}

#36


一般来说ActionListener应该直接implements到JFrame上,要不然很多的响应对象你都得不到。
class jframe extends JFrame implements ActionListener 这样。
然后你就可以在响应事件里获得你整个JFrame中的对象了。
package com;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ActionListenerTest extends JFrame implements ActionListener {
JComboBox jcb;
JButton jb1;
JButton jb2;
public ActionListenerTest(){
JPanel Jp =new JPanel();
String[] item = {"aaa","bbb","ccc"};
jcb = new JComboBox(item);
jb1 = new JButton("确定");
jb2 = new JButton("取消");

Jp.add(jcb);
Jp.add(jb1);
Jp.add(jb2);
this.add(Jp);
jcb.addActionListener(this);
jb1.addActionListener(this);
jb2.addActionListener(this);
this.setSize(200, 200);
this.setVisible(true);

}


public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub

Object o = e.getSource();

if(o instanceof JComboBox)
{
if(o==jcb)
{
System.out.println("jcb响应事件"+jcb.getSelectedItem());

}
}else if(o instanceof JButton){

if(o==jb1)
{

System.out.println("确定");

}
if(o==jb2)
{
System.out.println("取消");

}

}

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

}
}

#37


加上下面两句话,你的程序就可以运行了,只不过是一根黑竖杠在移动而已,那就是题外话了


// 构造方法,为gamecanvas1添加键盘处理事件
control() {
//*********************** add by dxc begin *********************/
B = new block();
//*********************** add by dxc end *********************/
}



public void actionPerformed(ActionEvent e) {
...........
//************************* add by dxc begin *********************/
jframe.gamecanvas1.requestFocus();
//************************* add by dxc end *********************/
}

#38


引用 35 楼 truediego 的回复:
那是因为你没有初始化B啊,所以才NullPoint的

control() {
B = new block(); //没有这句
}
老大,B我实例化了的啊,放在另一个构造函数control(int)里面实例化的。

#39


引用 37 楼 truediego 的回复:
加上下面两句话,你的程序就可以运行了,只不过是一根黑竖杠在移动而已,那就是题外话了


Java code

// 构造方法,为gamecanvas1添加键盘处理事件
    control() {
        //*********************** add by dxc begin *********************/
        B = new bl……

确实是这样,可以移动一根黑杠杠,我试过把jpanel单独作为一个类,也是出现这种情况?这是上面原因呢?

#40


引用 38 楼 tengfeng05 的回复:
老大,B我实例化了的啊,放在另一个构造函数control(int)里面实例化的。


晕,你调用这个没参数的构造方法,把B的实例化放在另外一个构造方法管啥用……

引用 39 楼 tengfeng05 的回复:
这是上面原因呢?

啥意思?




static block B; //设成static,就可以移动了

control() {
//这里空
}

#41


引用 40 楼 truediego 的回复:
引用 38 楼 tengfeng05 的回复:
老大,B我实例化了的啊,放在另一个构造函数control(int)里面实例化的。


晕,你调用这个没参数的构造方法,把B的实例化放在另外一个构造方法管啥用……


引用 39 楼 tengfeng05 的回复:
这是上面原因呢?

啥意思?



Java code


static block B; //设成st……
问题解决了,高手啊,收我当小弟吧老大!!!!!!!
话说回来,有点不明白。首先,此B和彼B到底有什么区别呢?那个黑竖杠的出现是不是因为在无参构造中实例化的B开启了另一个线程?为何加一个static又解决了?
概念有点模糊,记得书上说一个实例变量在类的不同实例化对象中是不同的,每个对象都拥有自己的实例变量,静态变量独立于类中的任何对象,对所有对象都是公共的,这句话该怎么理解?
老大送佛送到西,给小弟指点迷津一下吧

#42


没加static
也就是实例中起作用,你用无参的构造方法创建的control和带参的构造方法创建的control各含有一个B
即使你用同一个构造方法,调两遍,也是两个B,互相没关系

加了static
就实现了共产主义,你的就是我的,我的就是你的,在整个程序进程内起作用,仅此一个
所以即使你在无参构造方法里面没有实例化B,但是在带参构造方法里面实例化了,那就OK
只要在使用之前,任何一个时点任何一个地方实例化了,就OK


回到你的程序,没加static之前,移动的是无参构造方法里面创建的B,下落中的是带参构造方法创建的B
加了static之后,大家都对同一个B进行操作了

#43


实在不行、建议你“监听所有的事件”、对你感兴趣的事件--这里是“KeyEvent”进行处理
private java.awt.EventQueue myQueue=new java.awt.EventQueue(){
        public void dispatchEvent(AWTEvent ae){
            switch(ae.getID()){                   
                case KeyEvent.KEY_PRESSED:
//你的代码
break;//或return;
            }
            super.dispatchEvent(ae);
        }
    };

设置:java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().push(myQueue);

#44


     朋友你好,我的也出现过和你同样的问题,开始也是JPanel不能接受键盘事件,可是,从其他朋友对你的回答中,我找了很久才解决我的问题。同样地,刚开始我也是只用requestFocus()这个方法,没有作用,最后配合AJPanel构造函数(以红色显示)和a.requestFocus()(这所在位置相当重要,),成功了。如果你还没有解决的话,希望能帮助到你或者帮助到和我遇到同样问题的朋友。
    我增加一个JFrame类时可以在JFrame中监听键盘事件,可是换用JPanel(因为我想要减少代码)监听后失灵了。

我的解决方法:
public class AJPanel extends JPanel implements KeyListener {
    public AJPanel() {
        addKeyListener(this);
        public

      AJPanel() {
        addKeyListener(this);
    }
     public static void main(String[] args) {
        a.setOpaque(false);//a是AJPanel的对象
        JFrame frame = new JFrame();
        frame.setSize(509, 535);
        frame.setTitle("飞龙之方块");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setBackground(Color.darkGray);
        frame.setVisible(true);
        frame.setAlwaysOnTop(true);
        frame.add(a);
        a.start();
         a.requestFocus();//此处要特别重视,否则不能响应键盘事件
    }
}

#45


我也遇到了同样地问题 现在解决了 thanks everybody

#1


class control implements KeyListener

#2


坐等高手

#3


这个没做过,帮你顶一下

#4


看了你的source,觉得编译都不会过的

#5


我只把代码复制了一部分,控制类实现了KeyListene接口,另外,这个程序其他没有错误,已经能够运行,就差键盘不能控制,看了不少资料,一直没有解决问题。哪位大哥,来救救我啊!!!!!!

#6


话说,你implements了KeyListener了没

#7


问题补充,JPanel对象的创建我是放在窗体类的,接口实现放在了控制类,向左向右向下的操作方法放在的方块类

#8


引用 5 楼 tengfeng05 的回复:
我只把代码复制了一部分,控制类实现了KeyListene接口,另外,这个程序其他没有错误,已经能够运行,就差键盘不能控制,看了不少资料,一直没有解决问题。哪位大哥,来救救我啊!!!!!!
实现了,我只帖了部分代码

#9


引用 6 楼 luciferdevil 的回复:
话说,你implements了KeyListener了没
晕,点错。实现了,我只贴了部分代码。我看有些人资料说JPanel不能获取焦点,我试了N种方法,程序并不报错,就是和没加键盘事件一样

#10


引用楼主 tengfeng05 的回复:
在写一个俄罗斯方块游戏,JPanel游戏面板键盘监听不知哪里出了错,一直没有响应,下面是我的代码,各位大哥给小弟看一看,先在这里谢谢各位了!

class jframe extends JFrame
{  
  public static JPanel gamecanvas,nextcanvas; 
setVisible();

gamecanvas.addKeyListener(n……


1楼就回你了,你没包含KeyListener接口

#11


private class MyPanel extends javax.swing.JPanel{
        MyPanel(){
            enableEvents(AWTEvent.MOUSE_EVENT_MASK);
            enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
            enableEvents(AWTEvent.KEY_EVENT_MASK); 
        }
        protected void processEvent(AWTEvent e) {
            //添加你自己的事件处理代码
            switch(e.getID()){
            case KeyEvent.KEY_TYPED:

case KeyEvent.KEY_PRESSED:
        }
    };

#12


无论哪个控件、想接受键盘事件、必须先获得“焦点”
panel.requestFocus() ;

#13


引用 12 楼 dejinzhao 的回复:
无论哪个控件、想接受键盘事件、必须先获得“焦点”
panel.requestFocus() ;
我的JPanel对象是在窗体类中定义的,我不想让它作为一个单独的类,接口实现是在控制类中,你的代码是要将JPanel分出来单独作为一个类?另外,我设置焦点了,requestFocus(),setFocusabel()各种方法都用过,无效

#14


实现了KeyListener的话,加句
gamecanvas.setFocusable(true);

应该就行了

#15


你要是非用Jpanel的话,可以自己实现个Jpanel,包含KeyListener接口,然后把Jpanel作为监听器注册给JFrame:
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class KeyListenerTestPanel extends JPanel implements KeyListener {
JLabel Jb;
public KeyListenerTestPanel(){
Jb=new JLabel("测试");
this.add(Jb);
}

public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();

        switch (keyCode) {//判断键盘值

case 37:
Jb.setText("左");
System.out.println("左");
break;// 左
case 38:
Jb.setText("上");
System.out.println("上");
break;// 上
case 39:
Jb.setText("右");
System.out.println("右");
break;// 右
case 40:
Jb.setText("下");
System.out.println("下");
break;// 下

}
}

public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}

public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}
public static void main(String args[]){

JFrame jf = new JFrame();
jf.setSize(100, 100);
KeyListenerTestPanel  jp = new KeyListenerTestPanel();
jf.add(jp);
jf.addKeyListener(jp);
jf.setVisible(true);

}
}

#16


或者直接给JFrame注册监听事件
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class KeyListenerTest extends JFrame implements KeyListener {

JPanel gamecanvas;
JLabel Jb;
public KeyListenerTest(){
Jb=new JLabel("测试");
gamecanvas =new JPanel();
this.setSize(100, 100);
this.addKeyListener(this);
gamecanvas.add(Jb);
this.add(gamecanvas);
this.setVisible(true);

}


public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();

        switch (keyCode) {//判断键盘值

case 37:
Jb.setText("左");
System.out.println("左");
break;// 左
case 38:
Jb.setText("上");
System.out.println("上");
break;// 上
case 39:
Jb.setText("右");
System.out.println("右");
break;// 右
case 40:
Jb.setText("下");
System.out.println("下");
break;// 下

}

}

public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}

public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}

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

}
}

#17


引用 13 楼 tengfeng05 的回复:
我的JPanel对象是在窗体类中定义的,我不想让它作为一个单独的类,接口实现是在控制类中,你的代码是要将JPanel分出来单独作为一个类?另外,我设置焦点了,requestFocus(),setFocusabel()各种方法都用过,无效


我觉得你需要把你的布局晾出来了,setFocusable之后,就可以响应键盘了(已验证)
你现在无法获得事件,应该是被某些控件完全覆盖,因而获得不了焦点,或者被某些控件把键盘事件抢去,或者其它啥

#18


引用 16 楼 werosh 的回复:
或者直接给JFrame注册监听事件

Java code
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel……
感谢风动大地!看了你的代码,你是建议我把JPanel单独作为一个类吗?或者在窗体类中实现KeyListener事件?我是想在控制类中实现键盘事件,JPanel不作为一个单独类,这样有办法吗?

#19


引用 17 楼 truediego 的回复:
引用 13 楼 tengfeng05 的回复:
我的JPanel对象是在窗体类中定义的,我不想让它作为一个单独的类,接口实现是在控制类中,你的代码是要将JPanel分出来单独作为一个类?另外,我设置焦点了,requestFocus(),setFocusabel()各种方法都用过,无效


我觉得你需要把你的布局晾出来了,setFocusable之后,就可以响应键盘了(已验证)
你现在无法……
我的布局是NULL

#20


引用 19 楼 tengfeng05 的回复:
我的布局是NULL

我的意思是你的gamecanvas上面放了什么东西,是不是覆盖满了之类的

下面是我写的一个简单的例子,是可以的,你可以对照你的,看看有没有啥关键的区别
package to.shin.sai;

import java.awt.Container;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test4OutputScreen2Image extends JFrame {
/**
 * 
 */
private static final long serialVersionUID = 1L;

public static void main(String arg[]) {
new Test4OutputScreen2Image();
}

public Test4OutputScreen2Image() {
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Container contentPane = getContentPane();

JPanel keyPanel = new JPanel();
contentPane.add(keyPanel);

JLabel lbl = new JLabel();
lbl.setText("Hello");
keyPanel.add(lbl);

keyPanel.setFocusable(true);
keyPanel.addKeyListener(new controller());

setVisible(true);
}

private class controller implements KeyListener {

@Override
public void keyPressed(KeyEvent keyevent) {
System.out.println(keyevent.getKeyChar());
}

@Override
public void keyReleased(KeyEvent keyevent) {
// TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent keyevent) {
// TODO Auto-generated method stub

}

}

}

#21


很简单的,两个问题。
1.面板implements KeyListener;
2.JPanel上添加其他控件以后,被遮挡的部分是监听不到事件的,要在控件上添加KeyListener。

#22


引用 20 楼 truediego 的回复:
引用 19 楼 tengfeng05 的回复:
我的布局是NULL
我的意思是你的gamecanvas上面放了什么东西,是不是覆盖满了之类的

下面是我写的一个简单的例子,是可以的,你可以对照你的,看看有没有啥关键的区别

Java code
package to.shin.sai;

import java.awt.Container;
import java.awt.eve……

我的JPanel上什么也没有,就是充当画布,在上面画图。然后用键盘对图形进行控制,但是没效

#23


那还是建议你吧JPanel单独做个类吧,这样能把对JPanel操作完全封装到这个类里,其他地方用的时候直接new一下就成了。而且你做画布也要用到JPanel 的 Graphics。

#24


那就采用极端做法
1.在Keypressed里面加System.out
2.把不相关source全注掉,然后一段一段,一句一句释放,看效果

#25


引用 16 楼 werosh 的回复:
或者直接给JFrame注册监听事件

Java code
package com;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel……

我照着你的改了,还是没用。很奇怪,你上面的代码结构和我完全是一样,除了一点,我把main方法放在控制类中,但是我的为什么就不起作用呢?我的JPanel对象就是个空面板,只在上面画图·······

#26


main放哪没什么关系吧,代码发来看看。

#27


import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import java.net.*;
class jframe extends JFrame
{   
public static Canvas gamecanvas1,nextcanvas;
JPanel messagepanel;
JMenuBar mymenubar;
JMenu menu1,menu2,menu3,menu4;
  public static JMenuItem menu1_item1,menu1_item2,menu1_item3,
menu2_item1,
menu3_item1,menu3_item2,
  menu4_item1,menu4_item2,menu4_item3,menu4_item4,menu4_item5,
menu4_item6,menu4_item7,menu4_item8,menu4_item9,menu4_item10;
public static JButton startbutton,toolbutton1,toolbutton2,toolbutton3,toolbutton4;
  JLabel nextlabel,toollabel1,userscore1,userscore2;
  public static JTextField tooltext1,tooltext2,tooltext3,tooltext4,scoretext1,scoretext2,timetext;
public static JTextArea linkmessagetextarea;
  //取得内容面板
 jframe()  
  {
//窗体//
super("俄罗斯方块");
setSize(535,580);
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}});

//addKeyListener(new control());  
mymenubar=new JMenuBar();//创建菜单栏
gamecanvas1=new Canvas();//创建本机用户面板
messagepanel=new JPanel();//创建信息显示面板
//创建网络用户面板gamecanvas2=new gamecanvas();

Container con=getContentPane();
con.setLayout(null);//设置内容面板的布局模式为空布局
con.add(mymenubar);con.add(gamecanvas1);con.add(messagepanel);// con.add(gamecanvas2);
mymenubar.setBounds(0,0,535,20);
gamecanvas1.setBounds(15,35,300,500);
  messagepanel.setBounds(320,35,200,500);
  // gamecanvas2.setBounds(int x,int y,int a,int b);
  gamecanvas1.setBackground(Color.white);
messagepanel.setBackground(Color.lightGray);

//菜单栏//
menu1=new JMenu("游戏");
menu2=new JMenu("设置");
  menu3=new JMenu("帮助");
  menu4=new JMenu("关卡选择");
mymenubar.add(menu1);mymenubar.add(menu2);mymenubar.add(menu3);
menu1_item1=new JMenuItem("新游戏");menu1_item1.addActionListener(new control(1));
  menu1_item2=new JMenuItem("网络对战");menu1_item2.addActionListener(new control(2));
menu1_item3=new JMenuItem("退出");menu1_item3.addActionListener(new control(3));
menu2_item1=new JMenuItem("背景音乐");menu2_item1.addActionListener(new control(4));
menu3_item1=new JMenuItem("操作方法");menu3_item1.addActionListener(new control(5));
menu3_item2=new JMenuItem("关于···");menu3_item2.addActionListener(new control(6));
  menu4_item1=new JMenuItem("第一关");menu4_item1.addActionListener(new control(7));
menu4_item2=new JMenuItem("第二关");menu4_item2.addActionListener(new control(8));
  menu4_item3=new JMenuItem("第三关");menu4_item3.addActionListener(new control(9));
  menu4_item4=new JMenuItem("第四关");menu4_item4.addActionListener(new control(10));
  menu4_item5=new JMenuItem("第五关");menu4_item5.addActionListener(new control(11));
  menu4_item6=new JMenuItem("第六关");menu4_item6.addActionListener(new control(12));
  menu4_item7=new JMenuItem("第七关");menu4_item7.addActionListener(new control(13));
  menu4_item8=new JMenuItem("第八关");menu4_item8.addActionListener(new control(14));
menu4_item9=new JMenuItem("第九关");menu4_item9.addActionListener(new control(15));
menu4_item10=new JMenuItem("第十关");menu4_item10.addActionListener(new control(16));
menu1.add(menu1_item1); menu1.add(menu1_item2);menu1.add(menu1_item3);
menu2.add(menu2_item1); menu2.add(menu4);
menu3.add(menu3_item1); menu3.add(menu3_item2);
menu4.add(menu4_item1); menu4.add(menu4_item2);
  menu4.add(menu4_item3); menu4.add(menu4_item4);
  menu4.add(menu4_item5); menu4.add(menu4_item6);
  menu4.add(menu4_item7); menu4.add(menu4_item8);
  menu4.add(menu4_item9); menu4.add(menu4_item10);

  //创建NEXT信息子面板
  startbutton=new JButton("开始游戏");startbutton.addActionListener(new control(17));
nextlabel=new JLabel("NEXT");
nextcanvas=new Canvas();   
nextcanvas.setBackground(Color.white);

//创建道具信息子面板
toollabel1=new JLabel("道具");
toolbutton1=new JButton();toolbutton1.addActionListener(new control(18));
tooltext1=new JTextField("x 0",4);
toolbutton2=new JButton();toolbutton2.addActionListener(new control(19));
tooltext2=new JTextField("x 0",4);
toolbutton3=new JButton();toolbutton3.addActionListener(new control(20));
tooltext3=new JTextField("x 0",4);
toolbutton4=new JButton();toolbutton4.addActionListener(new control(21));
tooltext4=new JTextField("x 0",4);

//创建分数显示面板
  userscore1=new JLabel("分数");
  userscore2=new JLabel("对方分数");
scoretext1=new JTextField(6);
scoretext2=new JTextField(6);
timetext=new JTextField ("00:00:00",8);
linkmessagetextarea=new JTextArea("无连接",2,30);

//将NEXT信息子面板和道具信息子面板分数信息子面板添加到信息面板
messagepanel.setLayout(null);
messagepanel.add(startbutton);
messagepanel.add(nextlabel);
messagepanel.add(nextcanvas);
messagepanel.add(toollabel1);
  messagepanel.add(toolbutton1);messagepanel.add(tooltext1);
  messagepanel.add(toolbutton2);messagepanel.add(tooltext2);
messagepanel.add(toolbutton3);messagepanel.add(tooltext3);
messagepanel.add(toolbutton4);messagepanel.add(tooltext4);
messagepanel.add(userscore1);messagepanel.add(userscore2);
  messagepanel.add(scoretext1);messagepanel.add(scoretext2);
messagepanel.add(timetext);
messagepanel.add(linkmessagetextarea);
  
  startbutton.setBounds(60,15,80,30);
nextlabel.setBounds(87,55,40,20);
  nextcanvas.setBounds(63,85,75,90);

toollabel1.setBounds(88,190,40,20);
  toolbutton1.setBounds(10,220,40,40);tooltext1.setBounds(55,220,40,40);
  toolbutton2.setBounds(105,220,40,40);tooltext2.setBounds(150,220,40,40);
toolbutton3.setBounds(10,270,40,40);tooltext3.setBounds(55,270,40,40);
  toolbutton4.setBounds(105,270,40,40);tooltext4.setBounds(150,270,40,40);

userscore1.setBounds(45,325,60,20);userscore2.setBounds(115,325,60,20);
scoretext1.setBounds(25,355,63,30);scoretext2.setBounds(110,355,63,30);
timetext.setBounds(35,395,130,30);
linkmessagetextarea.setBounds(5,435,190,60);
   
setResizable(false);
  setVisible(true);
  gamecanvas1.setFocusable(true);
  gamecanvas1.addKeyListener(new control());
   }
}

#28


class block
{
  int row,col; //记录方块矩阵左上角在gamearea数组中的坐标
  int x,y;
  int blocktype,nexttype;//用来存储七种形态的方块
  int turntype;//用来存储方块的翻转状态
  int isblockdown;//用来记录游戏区底部堆积的方块行数
  int line;//记录可消去的行数
  static boolean isgameplay;
  Color color,nextcolor;
  Graphics g;
  int gamearea[][]=new int[29][15];
    
  int Block[][][][]=
{{{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}},
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}},   
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,1,1,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},
{{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},
{{1,0,0,0}, {1,0,0,0},{1,1,0,0},{0,0,0,0}}},

{{{0,1,1,0},{0,0,1,0},{0,0,1,0},{0,0,0,0}},
{{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}},
{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,1,0,0},{0,1,1,0},{0,0,1,0},{0,0,0,0}},
{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,1,0},{0,0,1,0},{0,0,0,0}},
{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,0,1,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,0,1,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}},

{{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}},

{{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
{{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}}};
//构造方法
block()
{
  blocktype=0;
  turntype=0;
  isblockdown=0;
  isgameplay=false;
   
}
//初始化游戏区域
public void initgamearea()
{
  for(int i=0;i<=24;i++)
  for(int j=0;j<=14;j++)
gamearea[i][j]=0;
  getblock();
}
//产生随机颜色
  public Color randomcolor()  
{   
Color C=new Color((new Double(Math.random() * 128)).intValue() + 128, (new Double(Math.random() * 128)).intValue() + 128, (new Double(Math.random() * 128)).intValue() + 128);  
return C;
  }
 //画NEXT方块
 public void drawnext(int nexttype,Color nextcolor)
 {
   g=jframe.nextcanvas.getGraphics();
   g.clearRect(0,0,65,90);
   g.setColor(nextcolor);
   switch(nexttype)
   {
     case 1:g.fill3DRect(27,5,20,20,true);
        g.fill3DRect(27,25,20,20,true);
g.fill3DRect(27,45,20,20,true);
g.fill3DRect(27,65,20,20,true);break;
     case 2:g.fill3DRect(17,15,20,20,true);
        g.fill3DRect(37,15,20,20,true);
g.fill3DRect(17,35,20,20,true);
g.fill3DRect(17,55,20,20,true);break;
 case 3:g.fill3DRect(17,15,20,20,true);
        g.fill3DRect(37,15,20,20,true);
g.fill3DRect(37,35,20,20,true);
g.fill3DRect(37,55,20,20,true);break;
 case 4:g.fill3DRect(17,15,20,20,true);
        g.fill3DRect(17,35,20,20,true);
g.fill3DRect(37,35,20,20,true);
g.fill3DRect(37,55,20,20,true);break;
 case 5:g.fill3DRect(37,15,20,20,true);
g.fill3DRect(37,35,20,20,true);
g.fill3DRect(17,35,20,20,true);
        g.fill3DRect(17,55,20,20,true);break;
 case 6:g.fill3DRect(17,25,20,20,true);
        g.fill3DRect(37,25,20,20,true);
g.fill3DRect(17,45,20,20,true);
g.fill3DRect(37,45,20,20,true);break;
 case 7:g.fill3DRect(27,25,20,20,true);
        g.fill3DRect(7,45,20,20,true);
g.fill3DRect(27,45,20,20,true);
g.fill3DRect(47,45,20,20,true);break;
    }
 }
//画方块方法
 public void drawblock(int draw)
  {  
   int line1=0,line2=0;
   g=jframe.gamecanvas1.getGraphics();
   g.setColor(color);
   switch(draw)
   {
    case 1: for(int i=0;i<=3;i++)
            for(int j=0;j<=3;j++)
            if(Block[blocktype][turntype][i][j]==1)
            g.fill3DRect((col+j)*20,(row+i)*20,20,20,true);
    case 2: for(int i=0;i<=3;i++)
            for(int j=0;j<=3;j++)
            if(Block[blocktype][turntype][i][j]==1)
              gamearea[row+i][col+j]=draw;
}
  }
  //刷新下落方块方法
  public void updateblock()
  {
    g=jframe.gamecanvas1.getGraphics();
g.setColor(Color.white);
for(int i=0;i<=3;i++)
    for(int j=0;j<=3;j++)
    if(Block[blocktype][turntype][i][j]==1)
    g.fillRect((col+j)*20,(row+i)*20,20,20);
  }
//消行方法
  public void deleteline()
  {
    int temp_line=0,i,j;
    g=jframe.gamecanvas1.getGraphics();
for(i=row;i<=row+4;i++)
  {
    if(temp_line==15) 
  {
    g.copyArea(0,0,300,(i-2)*20,0,20);
line++;
      }  
  for(j=0,temp_line=0;j<=14;j++)
    if(gamearea[i][j]==2) temp_line++;
  jframe.scoretext1.setText(Integer.toString((50+line*50)*line));
  }
  }
//初始化并得到新方块
  public void getblock()
  {  
row=0;
col=6;
isblockdown=0;
turntype=0;
blocktype=(int)(Math.random()*1000)%7;
color=randomcolor();
drawblock(1);
nexttype=(int)(Math.random()*1000)%7;
nextcolor=randomcolor();
drawnext(nexttype,nextcolor);
  }
  //得到下一个方块
  public void getnext()
  {
row=0;
col=6;
isblockdown=0;
turntype=0;
blocktype=nexttype;
color=nextcolor;
drawblock(1);
nexttype=(int)(Math.random()*1000)%7;
nextcolor=randomcolor();
drawnext(nexttype,nextcolor);
  }
//方块旋转方法
  public void turnblock()
  {  
if(moveable('T'))
{
updateblock();
if(turntype==3)
turntype=0;
else
turntype++;
drawblock(1);
}
  }
//方块右移方法
  public void moveright()
  {
if(moveable('R'))
{  
updateblock();
col++;
drawblock(1);
}
  }
//方块左移方法
  public void moveleft()
  {
if(moveable('L'))
{
updateblock();
col--;
drawblock(1);
}
  }
//方块下落方法
  public void blockdown()
  {
if(moveable('D'))
{
updateblock();  
row++;
drawblock(1);
}
else  
{
  drawblock(2);
  deleteline();
  isblockdown=1;
}
  }

//判断方块是否还能移动方法
  public boolean moveable(char direction)
  {
switch(direction)
{
case 'R':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(col+j>=14||gamearea[row+i][col+j+1]==2))
         return false;break;
case 'L':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(col+j<=0||gamearea[row+i][col+j-1]==2))
         return false;break;
case 'D':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(row+i>=24||gamearea[row+i+1][col+j]==2))
         return false;break;
case 'T':for(int i=0;i<=3;i++)
         for(int j=0;j<=3;j++)
         if(Block[blocktype][turntype][i][j]==1&&(col+j<=0||col+j>=14||row+i>=24||gamearea[row+i+1][col+j]==2||gamearea[row+i][col+j+1]==2||gamearea[row+i][col+j-1]==2))
         return false;break;
}  
return true;
  }  
 //判断游戏是否结束方法
public boolean isgameplay()
{
  if(gamearea[2][6]==2||gamearea[2][7]==2||gamearea[2][8]==2||gamearea[2][9]==2)
      return false;
  return true;
}
  //定时线程
  public class thread extends Thread
  {
public void run()
{  
while(isgameplay())
{
try{
sleep(control.time);
}catch(InterruptedException e){ }
  if(isblockdown==0)  
blockdown();
if(isblockdown==1)
getnext();
}
}  
  }
//返回内部类thread的引用实例
  public thread th()
  {
    return new thread();
  }   
}

#29


public class control implements ActionListener,KeyListener
{   
  static int time;
  block B;
  int currentbutton;
  //构造方法,为gamecanvas1添加键盘处理事件
  control()
  {
  }
  //构造方法,接受localuser类传递过来int型参数
control(int button)
{
  currentbutton=button;
  time=500;
  B=new block();
}  
  public void actionPerformed(ActionEvent e)
  {
switch(currentbutton)
{
case 1:B.initgamearea();
       B.th().start();
   time().start();break;
case 2:System.exit(0);break;
case 3:System.exit(0);break;
case 4:System.exit(0);break;
case 5:System.exit(0);break;
case 6:System.exit(0);break;
case 7:time=800;break;
case 8:time=750;break;
case 9:time=700;break;
case 10:time=625;break;
case 11:time=550;break;
case 12:time=475;break;
case 13:time=375;break;
case 14:time=275;break;
case 15:time=175;break;
  case 16:time=75;break;
case 17:if(!B.isgameplay)
{  
  
  B.isgameplay=true;
  B.initgamearea();
  B.th().start();
  time().start();
}
else  
{
try
{
  B.th().wait();
}catch(InterruptedException E){}
B.isgameplay=false;

break;
case 18:System.exit(0);break;
case 19:System.exit(0);break;
case 20:System.exit(0);break;
case 21:System.exit(0);break;
default:return;
}
  }

  public void keyPressed(KeyEvent e)
{  
  if(B.isgameplay)  
  {   
  switch(e.getKeyCode())
   {  
  case KeyEvent.VK_UP:System.out.println(0);break; 
  case KeyEvent.VK_DOWN:B.blockdown();break;  
  case KeyEvent.VK_LEFT:B.moveleft();break;  
  case KeyEvent.VK_RIGHT:B.moveright();break;  
  default:return;//用户按错键时结束方法
   }
  }
  return;
 }  
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
  
  public class gametime extends Thread
{  
  SimpleDateFormat starttimeformat= new SimpleDateFormat("HH:mm:ss");
      Date starttime = new Date();
  public void run()
  {
while(B.isgameplay())
    {  
 //B.time();
      try
 {
   sleep(1000);
     }catch(InterruptedException e){ }
  Date nowtime=new Date();
  Date time=new Date(nowtime.getTime()-starttime.getTime()-28800000);
          jframe.timetext.setText(starttimeformat.format(time));
     }
   }
  }
public gametime time()
{
   return new gametime();
}
  public static void main(String args[])
  {
    jframe frame=new jframe();
  }
}

#30


   setResizable(false);
      setVisible(true);
      gamecanvas1.setFocusable(true);
       gamecanvas1.addKeyListener(new control());
这句不对,你吧KeyListener添到panel上了,那个确实监听不到,换成this.addKeyListener看看

还有,你实例化太多监听器了,效率肯定不成,这些完全可以只new一个control

#31


setResizable(false);
  setVisible(true);
   this.addKeyListener(new control());

#32


引用 30 楼 werosh 的回复:
setResizable(false);
  setVisible(true);
  gamecanvas1.setFocusable(true);
  gamecanvas1.addKeyListener(new control());
这句不对,你吧KeyListener添到panel上了,那个确实监听不到,换成this.addKeyListener看看

还有,你实例化太多监听器……
照你说的试了,还是不行。另外,如果不new control(int)的话,怎么像它传递参数?

#33


你的button抢走了你的key事件
点了button之后,要把focus设回给你的gamecanvas

#34


引用 33 楼 truediego 的回复:
你的button抢走了你的key事件
点了button之后,要把focus设回给你的gamecanvas
这样我试过了,如果是向gamecanvas1注册的监听器,点了button后将focus设回来会发生exception,nullpointexception。如果是像jframe注册监听器,点了button后设回来仍旧没有反应,

#35


那是因为你没有初始化B啊,所以才NullPoint的

control() {
B = new block(); //没有这句
}

#36


一般来说ActionListener应该直接implements到JFrame上,要不然很多的响应对象你都得不到。
class jframe extends JFrame implements ActionListener 这样。
然后你就可以在响应事件里获得你整个JFrame中的对象了。
package com;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ActionListenerTest extends JFrame implements ActionListener {
JComboBox jcb;
JButton jb1;
JButton jb2;
public ActionListenerTest(){
JPanel Jp =new JPanel();
String[] item = {"aaa","bbb","ccc"};
jcb = new JComboBox(item);
jb1 = new JButton("确定");
jb2 = new JButton("取消");

Jp.add(jcb);
Jp.add(jb1);
Jp.add(jb2);
this.add(Jp);
jcb.addActionListener(this);
jb1.addActionListener(this);
jb2.addActionListener(this);
this.setSize(200, 200);
this.setVisible(true);

}


public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub

Object o = e.getSource();

if(o instanceof JComboBox)
{
if(o==jcb)
{
System.out.println("jcb响应事件"+jcb.getSelectedItem());

}
}else if(o instanceof JButton){

if(o==jb1)
{

System.out.println("确定");

}
if(o==jb2)
{
System.out.println("取消");

}

}

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

}
}

#37


加上下面两句话,你的程序就可以运行了,只不过是一根黑竖杠在移动而已,那就是题外话了


// 构造方法,为gamecanvas1添加键盘处理事件
control() {
//*********************** add by dxc begin *********************/
B = new block();
//*********************** add by dxc end *********************/
}



public void actionPerformed(ActionEvent e) {
...........
//************************* add by dxc begin *********************/
jframe.gamecanvas1.requestFocus();
//************************* add by dxc end *********************/
}

#38


引用 35 楼 truediego 的回复:
那是因为你没有初始化B啊,所以才NullPoint的

control() {
B = new block(); //没有这句
}
老大,B我实例化了的啊,放在另一个构造函数control(int)里面实例化的。

#39


引用 37 楼 truediego 的回复:
加上下面两句话,你的程序就可以运行了,只不过是一根黑竖杠在移动而已,那就是题外话了


Java code

// 构造方法,为gamecanvas1添加键盘处理事件
    control() {
        //*********************** add by dxc begin *********************/
        B = new bl……

确实是这样,可以移动一根黑杠杠,我试过把jpanel单独作为一个类,也是出现这种情况?这是上面原因呢?

#40


引用 38 楼 tengfeng05 的回复:
老大,B我实例化了的啊,放在另一个构造函数control(int)里面实例化的。


晕,你调用这个没参数的构造方法,把B的实例化放在另外一个构造方法管啥用……

引用 39 楼 tengfeng05 的回复:
这是上面原因呢?

啥意思?




static block B; //设成static,就可以移动了

control() {
//这里空
}

#41


引用 40 楼 truediego 的回复:
引用 38 楼 tengfeng05 的回复:
老大,B我实例化了的啊,放在另一个构造函数control(int)里面实例化的。


晕,你调用这个没参数的构造方法,把B的实例化放在另外一个构造方法管啥用……


引用 39 楼 tengfeng05 的回复:
这是上面原因呢?

啥意思?



Java code


static block B; //设成st……
问题解决了,高手啊,收我当小弟吧老大!!!!!!!
话说回来,有点不明白。首先,此B和彼B到底有什么区别呢?那个黑竖杠的出现是不是因为在无参构造中实例化的B开启了另一个线程?为何加一个static又解决了?
概念有点模糊,记得书上说一个实例变量在类的不同实例化对象中是不同的,每个对象都拥有自己的实例变量,静态变量独立于类中的任何对象,对所有对象都是公共的,这句话该怎么理解?
老大送佛送到西,给小弟指点迷津一下吧

#42


没加static
也就是实例中起作用,你用无参的构造方法创建的control和带参的构造方法创建的control各含有一个B
即使你用同一个构造方法,调两遍,也是两个B,互相没关系

加了static
就实现了共产主义,你的就是我的,我的就是你的,在整个程序进程内起作用,仅此一个
所以即使你在无参构造方法里面没有实例化B,但是在带参构造方法里面实例化了,那就OK
只要在使用之前,任何一个时点任何一个地方实例化了,就OK


回到你的程序,没加static之前,移动的是无参构造方法里面创建的B,下落中的是带参构造方法创建的B
加了static之后,大家都对同一个B进行操作了

#43


实在不行、建议你“监听所有的事件”、对你感兴趣的事件--这里是“KeyEvent”进行处理
private java.awt.EventQueue myQueue=new java.awt.EventQueue(){
        public void dispatchEvent(AWTEvent ae){
            switch(ae.getID()){                   
                case KeyEvent.KEY_PRESSED:
//你的代码
break;//或return;
            }
            super.dispatchEvent(ae);
        }
    };

设置:java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().push(myQueue);

#44


     朋友你好,我的也出现过和你同样的问题,开始也是JPanel不能接受键盘事件,可是,从其他朋友对你的回答中,我找了很久才解决我的问题。同样地,刚开始我也是只用requestFocus()这个方法,没有作用,最后配合AJPanel构造函数(以红色显示)和a.requestFocus()(这所在位置相当重要,),成功了。如果你还没有解决的话,希望能帮助到你或者帮助到和我遇到同样问题的朋友。
    我增加一个JFrame类时可以在JFrame中监听键盘事件,可是换用JPanel(因为我想要减少代码)监听后失灵了。

我的解决方法:
public class AJPanel extends JPanel implements KeyListener {
    public AJPanel() {
        addKeyListener(this);
        public

      AJPanel() {
        addKeyListener(this);
    }
     public static void main(String[] args) {
        a.setOpaque(false);//a是AJPanel的对象
        JFrame frame = new JFrame();
        frame.setSize(509, 535);
        frame.setTitle("飞龙之方块");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setBackground(Color.darkGray);
        frame.setVisible(true);
        frame.setAlwaysOnTop(true);
        frame.add(a);
        a.start();
         a.requestFocus();//此处要特别重视,否则不能响应键盘事件
    }
}

#45


我也遇到了同样地问题 现在解决了 thanks everybody