2014-11-27 1 views
1

Это мой кодПочему JDialog не запускает keyPressed метод прослушивания клавиш?

JToolBar customizeKeys = new JToolBar(); 
customizeKeys.add(new ChangeKeyListen("left")); 
private class ChangeKeyListen extends AbstractAction{ 
    private JDialog myDialog; 
    class KeyGetter extends KeyAdapter { 
     @Override 
     public void keyPressed(KeyEvent e) { 
      super.keyPressed(e); 
      OtherPanel.this.map(
         KeyEvent.getKeyText(e.getKeyCode()), 
              keyAction); 
      myDialog.setVisible(false); 
      myDialog.removeKeyListener(getKeyListeners()[0]); 
     } 
    }; 
    public ChangeKeyListen(String name) { 
     super(name); 
    } 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     myDialog = new JOptionPane().createDialog("Press a key"); 
     myDialog.setVisible(true); 
     myDialog.requestFocusInWindow(); 
     System.out.println(myDialog.getFocusableWindowState()); 
     myDialog.addKeyListener(new KeyGetter()); 
     System.out.println(myDialog.getKeyListeners()); 
    } 
} 

То, что я пытаюсь сделать здесь, когда пользователь нажимает на JButton, который был добавлен к JToolBar с атрибутами его действия, пользователь будет предложен с моим заказным диалогом коробка. Затем пользователь может нажать любую клавишу, чтобы закрыть диалоговое окно (оно на самом деле просто невидимо). Когда я запускаю приложение, все выглядит отлично. JToolBar выглядит правильно, и кнопка выглядит правильно. Когда я нажимаю кнопку, правильное поведение контроллера возникает при появлении диалогового окна. (Только видимо) Однако метод keyPressed ключа адаптера не запускается вообще, когда я нажимаю клавишу.

Что я сделал, чтобы отладить это, прежде всего, убедитесь, что JDialog в первую очередь может быть сконфигурирован, чтобы он мог получать ключевые события с клавиатуры. Я сделал это с этой линией

System.out.println(myDialog.getFocusableWindowState()); 

и то, что я получил на консоли, было правдой. Затем я убедился, что слушатель ключей был установлен. Я сделал это с

System.out.println(myDialog.getKeyListeners()); 

и это распечатаны

[Ljava.awt.event.KeyListener;@350b914b 

, который я предполагал, был правильный адрес памяти для объекта, выделенного из кучи.

Затем я проверил похожие темы.

Моя проблема не может быть Jbutton listener isn't triggered, why?, потому что появилось диалоговое окно, и я убедился, что прослушиватель клавиш был добавлен с помощью строки прослушивания клавиш печати. Я не мог использовать то, что пользователь сказал в Trying to use key Listener, потому что мне нужно прослушивать нажатие клавиши и использовать эту клавишу позже в моей программе. И это не помогает Why wont this KeyEvent work? , потому что мне нужна общая реакция на нажатия клавиш для получения нажатой клавиши.

Я знаю, что Keypressed не выполняется, потому что я поставил точку останова внутри метода, и этот оператор печати

System.out.println(KeyEvent.getKeyText(e.getKeyCode())); 

ничего на консоли не было печати.

Кто-нибудь знает, как я могу исправить эту проблему?

ответ

2

Вы добавляете KeyListener в диалог, созданный JOptionPane.

Однако основное внимание уделяется JButton в диалоговом окне. KeyEvents отправляются только компоненту с фокусом, поэтому ваш код прослушивания ключей никогда не вызывается.

Почему вы пытаетесь прослушать любую клавишу, чтобы закрыть диалоговое окно? Он НЕ удобен для пользователя. Пользователь не знает, как закрыть диалоговое окно, поскольку это не стандартное соглашение об пользовательском интерфейсе. Пользователь должен щелкнуть по кнопке, чтобы закрыть диалоговое окно.

Если вам действительно нужно прослушать любую нажатую клавишу, когда диалог открыт, проверьте Global Event Listeners, в котором показано, как вы можете использовать AWTEventListener для прослушивания любого ключевого события независимо от того, какой компонент имеет фокус.

+0

Я имею в виду, я мог бы включать в себя, что в диалоговом окне сообщения – committedandroider

+0

@committedandroider, такие компании, как Microsoft и Apple, тратить миллионы долларов на разработку последовательной интерфейсы, которые может использовать любой пользователь. Почему, по-вашему, вам нужно разработать собственный пользовательский интерфейс. Диалог должен быть закрыт нажатием кнопки или с помощью клавиши эвакуации. Вы не нажимаете ни одной клавиши, чтобы закрыть диалог. – camickr

+0

Да, спасибо. Я помню это. Но с точки зрения этого проекта я изменил myDialog.addKeyListener (новый KeyGetter()); просто добавитьKeyListener (новый KeyGetter()); myDialog.removeKeyListener (getKeyListeners() [0]); и удалитьKeyListener (getKeyListeners() [0]); так что слушатель клавиш будет прикреплен к Jbutton вместо этого. Но диалоговое окно все равно не будет закрыто .... – committedandroider

0

Имея дело с очень похожими проблемами, я призываю людей, которые хотят добавить слушателей к компонентам своего JDialog, чтобы следовать предложенному подходу here. Это позволяет больше контролировать компоненты.

В следующем примере демонстрируется пользовательское диалоговое окно, которое проверяет ввод пользователя при каждом изменении текста с помощью KeyListener.

public class DialogWithListener extends JDialog { 
    private JTextField textField = new JTextField(); 
    private boolean userPressedOk = false; 

    /** 
    * Creates a dialog that lets the user enter text in a text field. 
    * <p> 
    * Each time the user presses a key, the text is validated using the 
    * {@link Predicate}s in {@code predsAndMsgs}. If the text doesn't satisfy 
    * all predicates, the dialog shows the message associated with the first 
    * unsatisfied predicate. 
    * 
    * @param predsAndMsgs 
    *   a map from {@link Predicate}s to the messages we'll show to 
    *   users if the text they entered doesn't satisfy the predicates 
    */ 
    public DialogWithListener(Map<Predicate<String>, String> predsAndMsgs) { 

     JLabel textFieldLabel = new JLabel("Enter text:"); 

     // Show this if the text the user entered satisfies our predicates 
     String okText = "All good"; 

     JLabel statusLabel = new JLabel(okText); 

     Object[] paneContent = { textFieldLabel, textField, statusLabel }; 

     JButton okButton = new JButton("OK"); 
     okButton.addActionListener(e -> { 
      userPressedOk = true; 
      setVisible(false); 
     }); 

     Object[] options = { okButton }; 
     JOptionPane optionPane = new JOptionPane(paneContent, 
       JOptionPane.QUESTION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, 
       options); 

     getContentPane().add(optionPane); 
     setLocationRelativeTo(optionPane.getParent()); 

     setFocusTo(textField); 

     // Check the user input each time a key is released 
     textField.addKeyListener(new KeyAdapter() { 
      @Override 
      public void keyReleased(KeyEvent event) { 
       validate(predsAndMsgs, textField.getText(), okText, 
         statusLabel, okButton); 
      } 
     }); 

     setModal(true); 
     setResizable(false); 

     pack(); 
    } 

    /** 
    * Validates the {@code textToValidate}. 
    * <p> 
    * The {@link Predicate}s in {@link predsAndMsgs} determine whether the text 
    * is valid. If the text is invalid, we show the message that is associated 
    * with the predicate and disable this dialog's OK button. 
    * 
    * @param predsAndMsgs 
    *   a map from {@link Predicate}s that must hold for the 
    *   {@code textToValidate} to the messages we'll show to the user 
    *   if a predicate is not satisfied. 
    * @param textToValidate 
    *   we validate this text against the {@link Predicate}s in 
    *   {@link predsAndMsgs} 
    * @param okText 
    *   this text is shown if the {@code textToValidate} satisfies all 
    *   predicates 
    * @param statusLabel 
    *   a {@link JLabel} that either shows the {@link okText} or the 
    *   message of the first predicate that doesn't hold true for the 
    *   {@link textToValidate} 
    * @param okButton 
    *   we enable and disable this button depending on whether the 
    *   {@link textToValidate} is valid 
    */ 
    private void validate(Map<Predicate<String>, String> predsAndMsgs, 
      String textToValidate, String okText, JLabel statusLabel, 
      JButton okButton) { 
     // Get the first predicate that the text to validate doesn't satisfy 
     Optional<Predicate<String>> unsatisfiedPredMaybe = predsAndMsgs 
       .keySet().stream().filter(pred -> !pred.test(textToValidate)) 
       .findFirst(); 
     // At least one predicate was not satisfied 
     if (unsatisfiedPredMaybe.isPresent()) { 
      // Tell the user the text they entered can't be accepted 
      String msg = predsAndMsgs.get(unsatisfiedPredMaybe.get()); 
      statusLabel.setText(msg); 
      okButton.setEnabled(false); 
     } else { 
      statusLabel.setText(okText); 
      okButton.setEnabled(true); 
     } 
     pack(); 
    } 

    private void setFocusTo(JComponent comp) { 
     addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentShown(ComponentEvent ce) { 
       comp.requestFocusInWindow(); 
      } 
     }); 
    } 

    public Optional<String> display() { 
     userPressedOk = false; 
     // Because the dialog is modal it will block here 
     setVisible(true); 
     String dialogResult = null; 
     if (userPressedOk) { 
      dialogResult = textField.getText(); 
     } 
     return Optional.ofNullable(dialogResult); 
    } 
} 

И это, как вы создать и показать диалог:

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       UIManager.setLookAndFeel(UIManager 
         .getSystemLookAndFeelClassName()); 
      } catch (ClassNotFoundException | InstantiationException 
        | IllegalAccessException 
        | UnsupportedLookAndFeelException e) { 
       e.printStackTrace(); 
      } 
      createAndShowGUI(); 
     } 
    }); 
} 

private static void createAndShowGUI() { 
    JFrame frame = new JFrame(); 
    JButton showDialogButton = new JButton("Show Dialog"); 

    // Define the predicates that the user entered-text should satisfy and 
    // the messages shown to the user if it doesn't 
    Map<Predicate<String>, String> predicatesAndMessages = new HashMap<>(); 
    Predicate<String> dontMentionHisName = text -> !text 
      .contains("Voldemort"); 
    predicatesAndMessages.put(dontMentionHisName, 
      "Sssh! You can't say that!"); 

    DialogWithListener dialog = new DialogWithListener(
      predicatesAndMessages); 
    dialog.setTitle("My dialog"); 
    showDialogButton.addActionListener(e -> dialog.display().ifPresent(
      userText -> System.out.println(userText))); 

    frame.getContentPane().add(showDialogButton); 

    frame.pack(); 
    frame.setVisible(true); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^