【问题标题】:Problem with KeyListener and jframeKeyListener 和 jframe 的问题
【发布时间】:2011-06-02 12:30:28
【问题描述】:

我在俄罗斯方块游戏中遇到了 JFrame 和 KeyListerner 的问题。我有两个框架 - 一个带有开始按钮,第二个带有 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

        }
     }
}

【问题讨论】:

    标签: java swing jframe keylistener


    【解决方案1】:

    你的代码太大了,我想深入研究一下,但你想做的事情是可能的。

    无论哪种方式,我都建议您移动到一帧并可能使用CardLayout 或其他 GUI 项来隐藏和显示组件,因为在游戏开始时让用户更改屏幕是一个奇怪的 UI。将所有内容都放在一个框架中会更加用户友好。这可能会解决您当前的问题。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 感谢您的回答 :) 现在它可以工作了,但状态栏没有更新。更改后,当我单击“P”时,状态栏从 0 变为“暂停”。现在它不起作用。有什么想法吗?
      【解决方案3】:

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

      在您的面板类中:

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

      这意味着你的组件可以拥有焦点。

      其次,如果你想让你的jpanel*真正拥有焦点*,你可以调用他的方法

      panel.requestFocus();
      

      你应该在游戏开始时这样做,就在 pack/setVisible(true);并在每个动作监听器结束时使其失去焦点(通常是按钮的动作监听器)。

      问候, 斯蒂芬

      【讨论】:

      • 感谢您的回答 :) 现在它可以工作了,但状态栏没有更新。更改后,当我单击“P”时,状态栏从 0 变为“暂停”。现在它不起作用。有什么想法吗?
      • 不知道,你的代码太长了。但是一些一般性建议:1)当您在 JPanel 中绘制多于绘制时覆盖paintComponent 2)使用@Override 标签 3)为侦听器使用内部类,它比在主公共类中实现接口更具可扩展性 4)使用适配器而不是尽可能聆听。您将没有可覆盖的空方法(这对于维护来说总是令人困惑) TAdapter extends KeyAdapter
      【解决方案4】:

      您应该使用Key Bindings,而不是使用 KeyListener。

      【讨论】:

        【解决方案5】:

        keyListenerFrame 中对我不起作用。后来我发现问题是我的键控件要转到我在Frame中添加的Button。当我删除按钮时,按键控制回到框架并且 keyEvents 正在工作。 但是,即使将 Button 保留在 Frame 中,我也没有找到使用 keyEvents 的方法!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-04
          • 1970-01-01
          • 2017-07-24
          • 2012-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-05
          相关资源
          最近更新 更多