【问题标题】:Java switching jpanels and new panel doesnt respondJava切换jpanels和新面板没有响应
【发布时间】:2014-05-28 03:40:46
【问题描述】:

我用一个启动 JPanel 的 JFrame 开始我的游戏。当 JPanel 准备好后,该 JPanel 将继续进行下一个。我可以切换到新的 JPanel,但它不响应我的按键。第二个 JPanel 以前运行良好,所以我认为问题在于它们之间的切换。 (我去掉了一些不相关的方法)

public class GameRunner extends JFrame
{       
public GameRunner()
{
    super("Scrolling Shooter");

    Toolkit tk = Toolkit.getDefaultToolkit();  
    int width = ((int) tk.getScreenSize().getWidth());  
    int height = ((int) tk.getScreenSize().getHeight());  
    setSize(width, height);

    TitleScreen title = new TitleScreen(this);

    ((Component)title).setFocusable(true);
    getContentPane().add(title);

    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

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

public class TitleScreen extends JPanel implements KeyListener, Runnable
{
private JFrame frame;           //the JFrame
private ImageItem background;   //the background
private String name = "";       //the player's name

/**
 * Constructs a title screen
 * @param f the JFrame
 */
public TitleScreen (JFrame f)
{
    frame = f;

    ImageItem fix = new ImageItem();
    fix.fixMainPath();              //fixes the main path for all the ImageItems
    background = new ImageItem(0, 0, frame.getWidth(), frame.getHeight(), "splashscreen.png");  //makes background stretch between the top and bottom walls

    setVisible(true);
    addKeyListener(this);   
    new Thread(this).start();
}

/**
  * Draws the stuff on the screen
  * @param g some Graphics object
  */
protected void paintComponent(Graphics g)
{
    background.draw(g);
    if (!(name.equals("")))
    {
        g.setFont(g.getFont().deriveFont(80f));
        g.drawString(name, frame.getWidth() / 3, frame.getHeight() - 60);
    }
}

/**
 * When a key is typed it is added to the name
 * @param key the key typed
 */
public void keyTyped(KeyEvent key) 
{
    if (!(key.getKeyCode() == KeyEvent.VK_ENTER))
        name += key.getKeyChar();
}   

/**
 * Enter makes moves to the game if the name is ok
 * @param key the key pressed
 */
public void keyPressed(KeyEvent key)
{
    if (key.getKeyCode() == KeyEvent.VK_ENTER)
    {
        boolean isValid = false;

        if (name.length() > 20)
            JOptionPane.showMessageDialog(frame, "That name is too long. Try again.");

        if (!name.equals(""))
        {
            try {if (!hasBannedWord(name)) isValid = true;}         //breaks the loop if there are no banned words in the name
            catch (FileNotFoundException e) {e.printStackTrace();}
        }

        if (!isValid)
        {
            JOptionPane.showMessageDialog(frame, "Bad name. Try again.");
            name = "";
        }

        if (isValid)
        {
            ScrollingShooter game = new ScrollingShooter(frame, name);
            ((Component)game).setFocusable(true);
            frame.getContentPane().removeAll();
            frame.getContentPane().add(game);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    }   
}

public void run()
{
  try
  {
    while(true)
    {
       Thread.currentThread().sleep(0);
       repaint();
    }
  }     
  catch(Exception e){e.printStackTrace();}
}

【问题讨论】:

  • Thread.currentThread().sleep(0); repaint(); 不是做动画的正确方法。使用 Swing Timer 调用 repaint() 来制作动画。

标签: java swing jframe jpanel keyevent


【解决方案1】:

使用the key bindings API 而不是KeyListeners,它可以更好地控制生成关键事件所需的焦点级别

为了让KeyListener 生成KeyEvent,它注册到的组件必须是可聚焦的并且具有焦点。没有“简单”的方法可以保证组件可以获取/抓取焦点。

您还应该考虑使用 CardLayout 在屏幕之间移动,它的设计目的是为了让生活更轻松

您还应该调用super.paintComponent 以确保组件/Graphics 上下文已准备好进行绘制

【讨论】:

  • 所有 CardLayout 示例都显示了一些我不想要的按钮和东西。有没有办法在后台使用卡片而不将它们附加到按钮上?
  • CardLayout 是一个和其他布局管理器一样的布局管理器,您只需在主容器中添加您想要显示的任何容器,然后根据需要在视图之间切换
  • 我试过了,但它只显示一个空白的 JPanel。怎么了? TitleScreen title = new TitleScreen(this); ScrollingShooter game = new ScrollingShooter(this); JPanel cards = new JPanel(new CardLayout()); cards.add(title, "title"); cards.add(game, "game"); CardLayout cardLayout = (CardLayout) cards.getLayout(); cardLayout.show(cards, "title";
  • 你添加了cards 吗?
  • 不,我刚刚在倒数第二行做了cards.getLayout()
【解决方案2】:

您正在使用 KeyListener 并且 KeyListener 通常会遇到焦点问题,如果您尝试交换它们,这些问题会更加复杂。

我建议您改用 Key Bindings,它可以帮助您解决焦点问题,并且您可以将 JPanel 换成 CardLayout

【讨论】:

    猜你喜欢
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多