2012-06-24 22 views
7

Tôi gặp sự cố khi nhận được KeyBoardFocusManger để làm việc với toàn màn hình Window. Không có vấn đề gì, nó chỉ sẽ không nhận được đầu vào bàn phím. Tôi đã sử dụng một số System.exit(0) và một số println() để tìm kiếm bất kỳ lệnh gọi nào đến phương thức nhấn/phát hành/đã nhập, nhưng không có lỗi nào được ném. Tôi đã thử KeyListeners; nhưng sau khi đọc this, tôi đã đổi thành KeyboardFocusManager và điều tương tự vẫn xảy ra. Tôi thực sự đang tuyệt vọng; từ những gì tôi có thể đánh giá, các Window không nhận được trọng tâm của bàn phím?Cửa sổ toàn màn hình sẽ không nhận được đầu vào bàn phím bằng cách sử dụng KeyListener hoặc KeyBoardFocusManager

Đây là của tôi chính:

public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      // Determine if full-screen mode is supported directly 
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
      GraphicsDevice gs = ge.getDefaultScreenDevice(); 
      if (gs.isFullScreenSupported()) { 
       Frame frame = new Frame(gs.getDefaultConfiguration()); 
       SpaceInvaderUI spaceInvaderUI = new SpaceInvaderUI(frame); 
       // Enter full-screen mode 
       gs.setFullScreenWindow(spaceInvaderUI); 
      } else { 
       JOptionPane.showMessageDialog(null, "Does not support full screen!", "Error 0x01", JOptionPane.ERROR_MESSAGE); 
       System.exit(1); 
      } 
     } 
    }); 
} 

và đây là giao diện người dùng, trong đó có các KeyBoardFocusManger, và được thêm vào trong addListeners() phương pháp:

class SpaceInvaderUI extends Window { 

    private JPanel drawingPanel; 
    private Image background; 
    private JButton btnExit; 

    public SpaceInvaderUI(Frame frame) { 
     super(frame); 
     try { 
      background = ImageIO.read(getClass().getResourceAsStream("background.png")); 
     } catch (Exception ex) { 
      JOptionPane.showMessageDialog(null, "Could not extract resource: " + ex.getMessage(), "Error 0x02", JOptionPane.ERROR_MESSAGE); 
      System.exit(2); 
     } 
     createWindow(); 
    } 

    private void createComponents() throws HeadlessException { 
     drawingPanel = new DrawingPanel(background, this); 
     btnExit = new JButton("Exit"); 
    } 

    private void createWindow() { 
     createComponents(); 
     addListeners(); 
     addComponentsToWindow(); 
    } 

    private void addComponentsToWindow() { 
     add(drawingPanel, BorderLayout.CENTER); 
     add(btnExit, BorderLayout.SOUTH); 
    } 

    private void addListeners() { 
     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
     manager.addKeyEventDispatcher(new MyDispatcher()); 
     btnExit.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent ae) { 
       System.exit(0); 
      } 
     }); 
    } 

    private class MyDispatcher implements KeyEventDispatcher { 

     @Override 
     public boolean dispatchKeyEvent(KeyEvent e) { 
      if (e.getID() == KeyEvent.KEY_PRESSED) { 
       System.out.println("pressed"); 
       System.exit(0); 
      } else if (e.getID() == KeyEvent.KEY_RELEASED) { 
       System.out.println("released"); 
       System.exit(0); 
      } else if (e.getID() == KeyEvent.KEY_TYPED) { 
       System.out.println("Typed"); 
       System.exit(0); 
      } 
      return false; 
     } 
    } 
} 

Nút thoát là chỉ vì tôi đã mệt mỏi của giết chết ứng dụng của tôi thông qua taskmanager. Cuối cùng, đây là bảng điều khiển của tôi mà trò chơi sẽ diễn ra và nền của tôi được vẽ trên:

public class DrawingPanel extends JPanel { 

    private final Image background; 
    private final SpaceInvaderUI invaderUI; 

    DrawingPanel(Image background, SpaceInvaderUI invaderUI) { 
     this.background = background; 
     this.invaderUI = invaderUI; 
    } 

    @Override 
    protected void paintComponent(Graphics grphcs) { 
     super.paintComponent(grphcs); 
     grphcs.drawImage(background.getScaledInstance((int) invaderUI.getWidth(), (int) invaderUI.getHeight(), Image.SCALE_SMOOTH), 0, 0, this); 
    } 
} 

Cảm ơn bạn trước.

EDIT: Bây giờ tôi đã cố gắng sử dụng một keybinding trên tôi drawingPanel nhưng vẫn không có gì xảy ra khi tôi nhấn f2:

class SpaceInvaderUI extends Window { 

    private JPanel drawingPanel; 
    private Image background; 
    private JButton btnExit; 

    public SpaceInvaderUI(Frame frame) { 
     super(frame); 
     try { 
      background = ImageIO.read(getClass().getResourceAsStream("background.png")); 
     } catch (Exception ex) { 
      JOptionPane.showMessageDialog(null, "Could not extract resource: " + ex.getMessage(), "Error 0x02", JOptionPane.ERROR_MESSAGE); 
      System.exit(2); 
     } 
     createWindow(); 
    } 

    private void createComponents() throws HeadlessException { 
     drawingPanel = new DrawingPanel(background, this); 
     btnExit = new JButton("Exit"); 
    } 

    private void createWindow() { 
     createComponents(); 
     addListeners(); 
     addComponentsToWindow(); 
    } 

    private void addComponentsToWindow() { 
     add(drawingPanel, BorderLayout.CENTER); 
     add(btnExit, BorderLayout.SOUTH); 
    } 

    private void addListeners() { 
     Action exit = new AbstractAction() { 

      public void actionPerformed(ActionEvent e) { 
       System.exit(0); 
      } 
     }; 
     drawingPanel.getInputMap().put(KeyStroke.getKeyStroke("F2"), 
       exit); 
     btnExit.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent ae) { 
       System.exit(0); 
      } 
     }); 
    } 
} 
+0

Nó không phải là khung mà là cửa sổ và tôi có thể sử dụng nút để đóng cửa sổ nhưng tôi muốn trò chơi sử dụng phím 'Esc' để thoát và xuất hiện menu etc –

+0

Sau đó, tôi đoán KeyBinding chính xác là những gì có thể hoạt động bạn. –

Trả lời

5

Tại sao bạn đang sử dụng các thành phần AWT trong GUI Swing của bạn? Tôi sợ (nhưng không biết chắc chắn) rằng bằng cách làm điều này, bạn có thể mất một số chức năng Swing.

Nếu bạn chỉ chụp các phím chọn lựa chọn khóa để điều khiển trò chơi, hãy cân nhắc sử dụng Key Bindings.

Chỉnh sửa:
Không, thành phần AWT không có lỗi, nhưng vẫn có thể không nên sử dụng.

Chỉnh sửa 2:
Cửa sổ cấp cao nhất của bạn không tập trung vì một lý do nào đó. Tiếp tục kiểm tra mã ...

Sửa 3:
Sử dụng một JFrame làm việc cho tôi:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class Test3 { 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      GraphicsEnvironment ge = GraphicsEnvironment 
        .getLocalGraphicsEnvironment(); 
      GraphicsDevice gs = ge.getDefaultScreenDevice(); 
      if (gs.isFullScreenSupported()) { 
       SpaceInvaderUI spaceInvaderUI = new SpaceInvaderUI(gs.getDefaultConfiguration()); 
       gs.setFullScreenWindow(spaceInvaderUI); 
      } else { 
       JOptionPane.showMessageDialog(null, 
        "Does not support full screen!", "Error 0x01", 
        JOptionPane.ERROR_MESSAGE); 
       System.exit(1); 
      } 
     } 
     }); 
    } 
} 

// class SpaceInvaderUI extends JWindow { 
class SpaceInvaderUI extends JFrame { 

    private JPanel drawingPanel; 
    private Image background; 
    private JButton btnExit; 

    public SpaceInvaderUI(GraphicsConfiguration gc) { 
     super(gc); 
     createWindow(); 
     addKeyBindings(); 
     setUndecorated(true); 
    } 

    private void addKeyBindings() { 
     int condition = JPanel.WHEN_IN_FOCUSED_WINDOW; 
     InputMap inputMap = drawingPanel.getInputMap(condition); 
     ActionMap actionMap = drawingPanel.getActionMap(); 

     boolean released = false; 
     KeyStroke upArrowKeyStrokePressed = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, released); 
     String upArrowPressed = "up arrow pressed"; 
     inputMap.put(upArrowKeyStrokePressed , upArrowPressed); 
     actionMap.put(upArrowPressed, new AbstractAction() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      System.out.println("up arrow pressed"); 
     } 
     }); 

     released = true; 
     String upArrowReleased = "up arrow released"; 
     KeyStroke upArrowKeyStrokeReleased = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, released); 
     inputMap.put(upArrowKeyStrokeReleased , upArrowReleased); 
     actionMap.put(upArrowReleased , new AbstractAction() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      System.out.println("up arrow released"); 
     } 
     }); 

    } 

    private void createComponents() throws HeadlessException { 
     drawingPanel = new DrawingPanel(background, this); 
     btnExit = new JButton("Exit"); 
    } 

    private void createWindow() { 
     createComponents(); 
     addListeners(); 
     addComponentsToWindow(); 
    } 

    private void addComponentsToWindow() { 
     add(drawingPanel, BorderLayout.CENTER); 
     add(btnExit, BorderLayout.SOUTH); 
    } 

    private void addListeners() { 
//  KeyboardFocusManager manager = KeyboardFocusManager 
//   .getCurrentKeyboardFocusManager(); 
//  manager.addKeyEventDispatcher(new MyDispatcher()); 
     btnExit.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent ae) { 
      System.exit(0); 
     } 
     }); 
    } 
// 
// private class MyDispatcher implements KeyEventDispatcher { 
// 
//  @Override 
//  public boolean dispatchKeyEvent(KeyEvent e) { 
//   System.out.println("in dispatch. KeyEvent := " + e); 
//   if (e.getID() == KeyEvent.KEY_PRESSED) { 
//   System.out.println("pressed"); 
//   System.exit(0); 
//   } else if (e.getID() == KeyEvent.KEY_RELEASED) { 
//   System.out.println("released"); 
//   System.exit(0); 
//   } else if (e.getID() == KeyEvent.KEY_TYPED) { 
//   System.out.println("Typed"); 
//   System.exit(0); 
//   } 
//   return false; 
//  } 
// } 
} 

class DrawingPanel extends JPanel { 

    private final Image background; 
    private final SpaceInvaderUI invaderUI; 

    DrawingPanel(Image background, SpaceInvaderUI invaderUI) { 
     this.background = background; 
     this.invaderUI = invaderUI; 
     setBackground(Color.pink); 
    } 

    @Override 
    protected void paintComponent(Graphics grphcs) { 
     super.paintComponent(grphcs); 
    } 
} 
+0

aaaahhh Thật ngu ngốc với tôi, tôi đã tập trung vào việc thêm keybindings vào 'Window', điều hiển nhiên là không thể, không bao giờ nghĩ đến việc thêm nó vào bảng điều khiển của tôi. Cảm ơn rất nhiều :) –

+0

Tôi đã thử nó ra nhưng nó không hoạt động, không có gì xảy ra? –

+0

@DavidKroukamp: xem chỉnh sửa 3. –

4

Như thể hiện trong liên quan FullScreenTest này, bạn có thể sử dụng cùng một Action dụ cho nút ràng buộc chính.

Phụ Lục: @nIcE bò hỏi, Chúng ta có thể thêm nhiều hơn một phím trên cùngJComponentbằng cách sử dụngInputMapActionMap, và sử dụng cùng mộtAbstractActionlớp?

Có, bạn có thể thực hiện nhiều liên kết chính; Thỉnh thoảng tôi gọi số doClick() để nhận phản hồi nghe nhìn, như được hiển thị here.

+0

Tôi có thể đặt câu hỏi về KeyBinding không? Chúng ta có thể thêm, nhiều hơn một khóa trên cùng một 'JComponent' bằng cách sử dụng' InputMap' và 'ActionMap', và sử dụng cùng lớp' AbstractAction' không? –

+0

Cảm ơn bạn điều này có vẻ như thay thế duy nhất của tôi nếu tôi không thể làm cho phiên bản của tôi hoạt động –

Các vấn đề liên quan