2016-11-05 7 views
-2

Я знаю, что я разместил предыдущие вопросы по этой теме, но я размещаю новый здесь, потому что я создал MCVE, который мне нужен. Вот этот класс, который может воспроизвести проблему (если вы скопируете и вставьте этот код в свой редактор Java (но измените имя пакета), то он сможет успешно запускаться без проблем. Это полная тестовая программа):Keybindings случайно перестают работать из-за потери фокуса, может быть?

package com.blockhead7360.test.ppa; 

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 

import javax.swing.AbstractAction; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JTextArea; 
import javax.swing.KeyStroke; 

public class TotalKeyTest { 

static JTextArea area; 

static int i = 0; 

public TotalKeyTest(){ 
    JFrame frame = new JFrame("Test"); 
    frame.setPreferredSize(new Dimension(600, 600)); 
    frame.setMaximumSize(new Dimension(600, 600)); 
    frame.setMinimumSize(new Dimension(600, 600)); 

    JComponent comp = (JComponent) frame.getContentPane(); 
    frame.getRootPane().getRootPane().setActionMap(bindKeys(comp).getActionMap()); 
    frame.getRootPane().getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, bindKeys(comp).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)); 
    frame.pack(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setResizable(false); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true);   

} 

public static JComponent bindKeys(JComponent comp){ 
    comp.getInputMap().put(KeyStroke.getKeyStroke("pressed SPACE"), "pressSpace"); 
    comp.getActionMap().put("pressSpace", new AbstractAction(){ 

     private static final long serialVersionUID = 1L; 

     public void actionPerformed(ActionEvent e){ 
      System.out.println("pressed Space"); 
     } 
    }); 

    comp.getInputMap().put(KeyStroke.getKeyStroke("pressed A"), "pressLeft"); 
    comp.getActionMap().put("pressLeft", new AbstractAction(){ 

     private static final long serialVersionUID = 1L; 

     public void actionPerformed(ActionEvent e){ 
      System.out.println("pressed left"); 
     } 
    }); 
    comp.getInputMap().put(KeyStroke.getKeyStroke("released A"), "releaseLeft"); 
    comp.getActionMap().put("releaseLeft", new AbstractAction(){ 

     private static final long serialVersionUID = 1L; 

     public void actionPerformed(ActionEvent e){ 
      System.out.println("released left"); 
     } 
    }); 

    comp.getInputMap().put(KeyStroke.getKeyStroke("D"), "pressRight"); 
    comp.getActionMap().put("pressRight", new AbstractAction(){ 

     private static final long serialVersionUID = 1L; 

     public void actionPerformed(ActionEvent e){ 
      System.out.println("pressed right"); 
     } 
    }); 
    comp.getInputMap().put(KeyStroke.getKeyStroke("released D"), "releaseRight"); 
    comp.getActionMap().put("releaseRight", new AbstractAction(){ 

     private static final long serialVersionUID = 1L; 

     public void actionPerformed(ActionEvent e){ 
      System.out.println("released right"); 
     } 
    }); 
    return comp; 

} 

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

} 

Если вы хотите его как Pastebin, вот оно: http://pastebin.com/EhPJeAPC

в основном то, что происходит, когда я нажимаю пространство, и ключи D несколько раз в начале (короткие и длинные прессы), оно работает. После нескольких коротких и длинных нажатий он просто перестает работать!

Может кто-нибудь помочь?

EDIT: BTW Я знаю, что код включает frame.getRootPane() вместо того, чтобы просто использовать frame.add(), но это было там, потому что я пытался кое-что изложить. Я могу изменить его, если хочешь.

EDIT: Я узнал, что он отлично работает, если я использую клавиши со стрелками вместо клавиш A и D. Я не знаю, почему, но я собираюсь бросить это.

+1

(1-) и что происходит, когда вы тестируете рабочий код, который был предоставлен вам в вашем предыдущем вопросе ??? Почему вы ожидаете от нас отладки вашего кода, когда вам уже предоставлен рабочий код? Поэтому вместо того, чтобы мы потратили время на тестирование кода. Вы тратите время на тестирование нашего кода. Если наш код не работает, возможно, проблема с версией/платформой. – camickr

+0

'Я узнал, что он отлично работает, если я использую клавиши со стрелками' - как вы это узнали? Вы наконец-то протестировали ранее данный код? – camickr

ответ

1

Вы получаете неверную карту ввода для contentPane. Вы используете по умолчанию getInputMap(), которая использует карту по умолчанию JComponent.WHEN_FOCUSED, когда вы должны использовать более конкретные getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)

Например, мой MCVE:

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class TotalKeyTest2 extends JPanel { 
    private static final int PREF_W = 600; 
    private static final int PREF_H = PREF_W; 
    private int condition = WHEN_IN_FOCUSED_WINDOW; 
    private InputMap inputMap = getInputMap(condition); 
    private ActionMap actionMap = getActionMap(); 

    public TotalKeyTest2() { 
     setBindings(); 
    } 

    private void setBindings() {   
     insertKey(KeyEvent.VK_SPACE, "Space"); 
     insertKey(KeyEvent.VK_A, "Left"); 
     insertKey(KeyEvent.VK_D, "Right"); 
    } 

    private void insertKey(int keyCode, String text) { 
     KeyStroke pressed = KeyStroke.getKeyStroke(keyCode, 0, false); 
     KeyStroke released = KeyStroke.getKeyStroke(keyCode, 0, true); 
     String pressedActionName = text + " Pressed"; 
     String releasedActionName = text + " Released"; 
     Action pressedAction = new MyAction(pressedActionName); 
     Action releasedAction = new MyAction(releasedActionName);   
     inputMap.put(pressed, pressedActionName); 
     inputMap.put(released, releasedActionName); 
     actionMap.put(pressedActionName, pressedAction); 
     actionMap.put(releasedActionName, releasedAction); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class MyAction extends AbstractAction { 

     public MyAction(String name) { 
      super(name); 
     } 


     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println(getValue(NAME)); 
     } 
    } 

    private static void createAndShowGui() { 
     TotalKeyTest2 mainPanel = new TotalKeyTest2(); 

     JFrame frame = new JFrame("TotalKeyTest2"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 
+0

Ничего не изменилось. Он по-прежнему не работает ... – Blockhead7360

+0

@ Blockhead7360: что происходит, когда вы пытаетесь использовать код выше? –

+0

Он по-прежнему делает то же самое. Сначала он работает, но после того, как я начинаю долго нажимать клавиши или нажимать их быстрее, он в конечном итоге перестает отправлять отладочные сообщения, когда я нажимаю клавиши. – Blockhead7360