KeyListener和jframe的问题

时间:2011-06-02 12:30:28

标签: java swing jframe keylistener

我在俄罗斯方块游戏中遇到了JFrame和KeyListerner的问题。我有两个框架 - 一个带有Start Button,另一个带有Board。在第二帧我想从键盘控制形状,但是当我点击开始我不能这样做。当我取消激活第一帧时 - 一切都好。我知道我必须专注于第二帧,我尝试这样做,但没有效果。有人能帮助我吗? 第一帧:

package tetris;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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


public class Tetris implements ActionListener {
public Tetris() {
initComponents();
}
Component contentPane;
JLabel statusbar  = new JLabel(" 0"); 
JLabel name  = new JLabel("Tetris"); 
JButton startbut = new JButton("Start");
JFrame window = new JFrame();
JPanel panelStart = new JPanel();
JPanel game = new JPanel();
int nameSize=24;
Font fontName = new Font("Dialog", Font.BOLD, nameSize);
BorderLayout borderLayout = new BorderLayout();
Board board = new Board(this);

public void initComponents() {
    window.setBounds(500,200,200,400);
    window.setTitle("Tetris");
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);

    window.add(panelStart);
    window.add(game);
    panelStart.setLayout (null);
    panelStart.setVisible(true);
    window.setContentPane(panelStart);

    name.setSize(70,25);
    name.setLocation(53,10);
    name.setFont(fontName);
    panelStart.add(name);
    startbut.setSize(70,25);
    startbut.setLocation(50,80);
    panelStart.add(startbut);
    startbut.addActionListener(this);
  }

public void initGame() {

    game.setLayout (borderLayout);
    panelStart.setVisible(false);
    window.remove(panelStart);

    game.setVisible(true);
    window.setContentPane(game);




    game.setFocusable(true);
    statusbar = new JLabel(" 0");
   game.add(statusbar, BorderLayout.SOUTH);
     game.add(board);
   board.start();

 }
 public JLabel getStatusBar() {
   return statusbar;
 }
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == startbut)
{
    initGame();

}
}


}

董事会代码:

package tetris;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;


import tetris.Shape.Tetrominoes;


public class Board extends JPanel implements ActionListener      {


    final int BoardWidth = 10;
    final int BoardHeight = 22;

    Timer timer;
    boolean isFallingFinished = false;
    boolean isStarted = false;
    boolean isPaused = false;
    int numLinesRemoved = 0;
    int curX = 0;
    int curY = 0;
    JLabel statusbar;
    Shape curPiece;
    Tetrominoes[] board;



    public Board(Tetris parent) {


    //   setFocusable(true);
       curPiece = new Shape();
       timer = new Timer(400, this);
       timer.start(); 

       statusbar =  parent.getStatusBar();
       board = new Tetrominoes[BoardWidth * BoardHeight];
       KeyListener keyListener = new TAdapter();
       addKeyListener(keyListener);
       repaint();
       clearBoard();  

    }

    public void actionPerformed(ActionEvent e) {
        if (isFallingFinished) {
            isFallingFinished = false;
            newPiece();
        } else {
            oneLineDown();
        }
    }


    int squareWidth() { return (int) getSize().getWidth() / BoardWidth; }
    int squareHeight() { return (int) getSize().getHeight() / BoardHeight; }
    Tetrominoes shapeAt(int x, int y) { return board[(y * BoardWidth) + x]; }


    public void start()
    {
        if (isPaused)
            return;

        isStarted = true;
        isFallingFinished = false;
        numLinesRemoved = 0;
        clearBoard();

        newPiece();
        timer.start();
    }

    private void pause()
    {
        if (!isStarted)
            return;

        isPaused = !isPaused;
        if (isPaused) {
            timer.stop();
            statusbar.setText("paused");
        } else {
            timer.start();
            statusbar.setText(String.valueOf(numLinesRemoved));
        }
        repaint();
    }

    public void paint(Graphics g)
    { 
        super.paint(g);

        Dimension size = getSize();
        int boardTop = (int) size.getHeight() - BoardHeight * squareHeight();


        for (int i = 0; i < BoardHeight; ++i) {
            for (int j = 0; j < BoardWidth; ++j) {
                Tetrominoes shape = shapeAt(j, BoardHeight - i - 1);
                if (shape != Tetrominoes.NoShape)
                    drawSquare(g, 0 + j * squareWidth(),
                               boardTop + i * squareHeight(), shape);
            }
        }

        if (curPiece.getShape() != Tetrominoes.NoShape) {
            for (int i = 0; i < 4; ++i) {
                int x = curX + curPiece.x(i);
                int y = curY - curPiece.y(i);
                drawSquare(g, 0 + x * squareWidth(),
                           boardTop + (BoardHeight - y - 1) * squareHeight(),
                           curPiece.getShape());
            }
        }
    }

    private void dropDown()
    {
        int newY = curY;
        while (newY > 0) {
            if (!tryMove(curPiece, curX, newY - 1))
                break;
            --newY;
        }
        pieceDropped();
    }

    private void oneLineDown()
    {
        if (!tryMove(curPiece, curX, curY - 1))
            pieceDropped();
    }


    private void clearBoard()
    {
        for (int i = 0; i < BoardHeight * BoardWidth; ++i)
            board[i] = Tetrominoes.NoShape;
    }

    private void pieceDropped()
    {
        for (int i = 0; i < 4; ++i) {
            int x = curX + curPiece.x(i);
            int y = curY - curPiece.y(i);
            board[(y * BoardWidth) + x] = curPiece.getShape();
        }

        removeFullLines();

        if (!isFallingFinished)
            newPiece();
    }

    private void newPiece()
    {
        curPiece.setRandomShape();
        curX = BoardWidth / 2 + 1;
        curY = BoardHeight - 1 + curPiece.minY();

        if (!tryMove(curPiece, curX, curY)) {
            curPiece.setShape(Tetrominoes.NoShape);
            timer.stop();
            isStarted = false;
            statusbar.setText("game over");
        }
    }

    private boolean tryMove(Shape newPiece, int newX, int newY)
    {
        for (int i = 0; i < 4; ++i) {
            int x = newX + newPiece.x(i);
            int y = newY - newPiece.y(i);
            if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
                return false;
            if (shapeAt(x, y) != Tetrominoes.NoShape)
                return false;
        }

        curPiece = newPiece;
        curX = newX;
        curY = newY;
        repaint();
        return true;
    }

    private void removeFullLines()
    {
        int numFullLines = 0;

        for (int i = BoardHeight - 1; i >= 0; --i) {
            boolean lineIsFull = true;

            for (int j = 0; j < BoardWidth; ++j) {
                if (shapeAt(j, i) == Tetrominoes.NoShape) {
                    lineIsFull = false;
                    break;
                }
            }

            if (lineIsFull) {
                ++numFullLines;
                for (int k = i; k < BoardHeight - 1; ++k) {
                    for (int j = 0; j < BoardWidth; ++j)
                         board[(k * BoardWidth) + j] = shapeAt(j, k + 1);
                }
            }
        }

        if (numFullLines > 0) {
            numLinesRemoved += numFullLines;
            statusbar.setText(String.valueOf(numLinesRemoved));
            isFallingFinished = true;
            curPiece.setShape(Tetrominoes.NoShape);
            repaint();
        }
     }

    private void drawSquare(Graphics g, int x, int y, Tetrominoes shape)
    {
        Color colors[] = { new Color(0, 0, 0), new Color(204, 102, 102), 
            new Color(102, 204, 102), new Color(102, 102, 204), 
            new Color(204, 204, 102), new Color(204, 102, 204), 
            new Color(102, 204, 204), new Color(218, 170, 0)
        };


        Color color = colors[shape.ordinal()];

        g.setColor(color);
        g.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2);

        g.setColor(color.brighter());
        g.drawLine(x, y + squareHeight() - 1, x, y);
        g.drawLine(x, y, x + squareWidth() - 1, y);

        g.setColor(color.darker());
        g.drawLine(x + 1, y + squareHeight() - 1,
                         x + squareWidth() - 1, y + squareHeight() - 1);
        g.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,
                         x + squareWidth() - 1, y + 1);

    }
    public boolean isFocusable() {
        return true;
    }
  public class TAdapter implements KeyListener  {
          public void keyTyped(KeyEvent e) {
          }
         public void keyPressed(KeyEvent e) {
             if (!isStarted || curPiece.getShape() == Tetrominoes.NoShape) {  
                 return;
             }

             int keycode = e.getKeyCode();

             if (keycode == 'p' || keycode == 'P') {
                 pause();
                 return;
             }

             if (isPaused)
                 return;

             switch (keycode) {
             case KeyEvent.VK_LEFT:
                 tryMove(curPiece, curX - 1, curY);
                 break;
             case KeyEvent.VK_RIGHT:
                 tryMove(curPiece, curX + 1, curY);
                 break;
             case KeyEvent.VK_DOWN:
                 tryMove(curPiece.rotateRight(), curX, curY);
                 break;
             case KeyEvent.VK_UP:
                 tryMove(curPiece.rotateLeft(), curX, curY);
                 break;
             case KeyEvent.VK_SPACE:
                 dropDown();
                 break;
             case 'd':
                 oneLineDown();
                 break;
             case 'D':
                 oneLineDown();
                 break;
             }

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

        }
     }
}

5 个答案:

答案 0 :(得分:2)

你的代码很大,我想要挖掘,但你想做的事情是可能的。

无论哪种方式,我建议您移动到一个框架,并可能使用CardLayout或另一个GUI项来隐藏和显示组件,因为在游戏启动时让用户更改屏幕是一个奇怪的UI。只需将它全部放在一个框架中,它将更加用户友好。这可能会解决您当前的问题。

答案 1 :(得分:1)

在这里,代码太大了,无法挖掘。但是,如果您在设置焦点时遇到问题,请尝试frame.requestFocus();

答案 2 :(得分:1)

首先,想要获取焦点的JPanel必须是可聚焦的或焦点可遍历的。 您应该考虑重写isFocusTraversable以返回true。

在您的小组课程中:

@Override
public boolean isFocusTraversable()
{
  return true;
}//met

这意味着您的组件可以具有焦点。

其次,如果你希望你的jpanel *实际上具有焦点*,你可以调用他的方法

panel.requestFocus();

你应该在游戏开始时,就在pack / setVisible(true)之后;并且在每个actionlistener的末尾都会使它失去焦点(通常是按钮的动作)。

此致  斯特凡

答案 3 :(得分:1)

您应该使用Key Bindings

,而不是使用KeyListener

答案 4 :(得分:0)

框架中,

keyListener 无效。后来我发现问题是我的键控件转到了我在Frame中添加的 Button 。当我删除Button时,键控制器返回到框架,keyEvents正在工作。 但即使将Button保持在Frame中,我也没有找到使用keyEvents的方法!