KeyListener 和 jframe 的问题

发布于 2024-11-11 17:17:44 字数 10358 浏览 5 评论 0原文

我在俄罗斯方块游戏中遇到 JFrame 和 KeyListerner 问题。我有两个框架 - 第一个带有“开始”按钮,第二个带有“板”。在第二帧中,我想从键盘控制形状,但是当我单击开始时我无法做到这一点。当我禁用第一帧时 - 一切都很好。我知道我必须专注于第二帧,我尝试这样做,但没有效果。有人可以帮助我吗? 第一帧:

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

        }
     }
}

I've got problem with JFrame and KeyListerner in Tetris game. I've got two frames - one with Start Button and second with Board. In the second frame I want to control shapes from keyboard, but when I click start I can't do that. When I disactivate first frame - everything is ok. I know I have to focus on second frame and I tried do that, but with no effect. Could someone help me?
First frame:

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();

}
}


}

Board code:

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

        }
     }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

柒夜笙歌凉 2024-11-18 17:17:44

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

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

Your code is to large for me to want to dig through, but what you want to do is possible.

Either way, I would suggest you move to one frame and possibly use a CardLayout or another GUI item to hide and show components because having the user change screens when the game starts is a strange UI. It will be more user friendly to just have it all in one frame. And this might fix your current issue.

得不到的就毁灭 2024-11-18 17:17:44

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

Same here, the code is too large to dig. However if you are facing problems in setting the focus try frame.requestFocus();

半世蒼涼 2024-11-18 17:17:44

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

在您的面板类中:

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

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

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

panel.requestFocus();

您应该在游戏开始时、在 pack/setVisible( true ); 之后执行此操作。在每个动作监听器的末尾,这将使其失去焦点(通常是按钮的动作监听器)。

问候,
史蒂芬

First, a JPanel that wants to grab focus has to be focusable or focus traversable.
You should consider overriding isFocusTraversable to return true.

In your panel class :

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

This means your component can have focus.

Second, if you want your jpanel to* actually have the focus*, you can call his method

panel.requestFocus();

you should do that at the beginning of the game, right after the pack/setVisible( true ); and at the end of every actionlistener that will make it loose focus (typically buttons'actionlisteners).

Regards,
Stéphane

执笔绘流年 2024-11-18 17:17:44

您应该使用按键绑定,而不是使用KeyListener。

Instead of using a KeyListener you should be using Key Bindings.

如果没结果 2024-11-18 17:17:44

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

keyListener was not working for me in Frame. Later I found out that the problem was that my key controls were going to the Button that I had added in the Frame. When I removed the Button, The key control went back to the frame and keyEvents were working.
But I have not found a way to use keyEvents even after keeping the Button in Frame!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文