2012-12-05 13 views
35

Uczę się teraz klasy Swing i wszystkiego na ten temat. Mam ten program zabawkowy, który układałem, który podpowiada nazwę, a następnie przedstawia JOptionPane z komunikatem "Wprowadziłeś (twoje imię)". Przycisk przesyłania, którego używam, można kliknąć tylko, ale chciałbym, aby działał również za pomocą przycisku Enter. Próbowałem dodać KeyListener, jak zaleca się w książce Java używam (Eventful Java, Bruce Danyluk i Murtagh).Po naciśnięciu przycisku "Wyślij" przycisk "Enter", a nie tylko za pomocą MouseClick

NamePrompt enter image description here

To jest mój kod:

import java.awt.BorderLayout; 
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; 
import javax.swing.JTextField; 


public class NamePrompt extends JFrame{ 


    private static final long serialVersionUID = 1L; 

    String name; 

    public NamePrompt(){ 

     setLayout(new BorderLayout()); 

     JLabel enterYourName = new JLabel("Enter Your Name Here:"); 
     JTextField textBoxToEnterName = new JTextField(21); 
     JPanel panelTop = new JPanel(); 
     panelTop.add(enterYourName); 
     panelTop.add(textBoxToEnterName); 

     JButton submit = new JButton("Submit"); 
     submit.addActionListener(new SubmitButton(textBoxToEnterName)); 
     submit.addKeyListener(new SubmitButton(textBoxToEnterName)); 
     JPanel panelBottom = new JPanel(); 
     panelBottom.add(submit); 

     //Add panelTop to JFrame 
     add(panelTop, BorderLayout.NORTH); 
     add(panelBottom, BorderLayout.SOUTH); 

     //JFrame set-up 
     setTitle("Name Prompt Program"); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     pack(); 
     setLocationRelativeTo(null); 


    } 



    public static void main(String[] args) { 
     NamePrompt promptForName = new NamePrompt(); 
     promptForName.setVisible(true); 
    } 


} 

I to jest klasa ActionListener, KeyListener:

import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 

import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JTextField; 


public class SubmitButton implements ActionListener, KeyListener { 

    JTextField nameInput; 


    public SubmitButton(JTextField textfield){ 
     nameInput = textfield; 
    } 

    @Override 
    public void actionPerformed(ActionEvent submitClicked) { 

     Component frame = new JFrame(); 
     JOptionPane.showMessageDialog(frame , "You've Submitted the name " + nameInput.getText()); 
    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     if (e.getKeyCode()==KeyEvent.VK_ENTER){ 
      System.out.println("Hello"); 
     } 
     Component frame = new JFrame(); 
     JOptionPane.showMessageDialog(frame , "You've Submitted the name " + nameInput.getText()); 

    } 

    @Override 
    public void keyReleased(KeyEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyTyped(KeyEvent arg0) { 

    } 
} 

Odpowiedz

88

Istnieje prosty trik do tego. Po skonstruowana ramkę ze wszystkich przycisków it to zrobić:

frame.getRootPane().setDefaultButton(submitButton); 

Dla każdej ramki, można ustawić domyślny przycisk, który automatycznie wysłuchać klawisz Enter (a może jakieś inne wydarzenia nie jestem świadomy) . Po naciśnięciu Enter w tej ramce zostanie wywołana metoda ActionListeners ich metoda actionPerformed().


A problem z kodem miarę widzę jest to, że dialog wyskakuje za każdym razem trafisz na klucz, bo nie umieścić go w IF-ciele. Spróbuj zmienić go na to:

@Override 
public void keyPressed(KeyEvent e) { 
    if (e.getKeyCode()==KeyEvent.VK_ENTER){ 
     System.out.println("Hello"); 

     JOptionPane.showMessageDialog(null , "You've Submitted the name " + nameInput.getText()); 
    } 

} 

UPDATE: znalazłem to, co jest złego w kodzie. Dodajesz kluczowego odbiornika do przycisku Prześlij zamiast do Pola tekstowego. Zmienić swój kod do tego:

SubmitButton listener = new SubmitButton(textBoxToEnterName); 
textBoxToEnterName.addActionListener(listener); 
submit.addKeyListener(listener); 
+1

To działa! Czy możesz wyjaśnić, dlaczego to działa? Co się stanie, jeśli chcę, aby przycisk Wyślij został naciśnięty klawiszem spacji? (tj. gdyby było więcej niż jeden przycisk). – CodyBugstein

+0

Wystarczająco jasne? Chętnie pomogę :) –

+0

Właściwie, zanim zaimplementowałem twoje rozwiązanie, okno dialogowe nie pojawiło się dla żadnego klawisza (nawet Enter). Co było nie tak? – CodyBugstein

12

Można użyć panelu górnego pojemniki poziomie głównym, aby ustawić domyślny przycisk, który pozwoli odpowiedzieć na to enter.

SwingUtilities.getRootPane(submitButton).setDefaultButton(submitButton); 

To, oczywiście, zakłada dodaniu przycisku do ważnego pojemnika;)

AKTUALIZACJA

Jest to prosty przykład za pomocą JRootPane#setDefaultButton i klawiszy API

public class DefaultButton { 

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

    public DefaultButton() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

     }); 
    } 

    public class TestPane extends JPanel { 

     private JButton button; 
     private JLabel label; 
     private int count; 

     public TestPane() { 

      label = new JLabel("Press the button"); 
      button = new JButton("Press me"); 

      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridy = 0; 
      add(label, gbc); 
      gbc.gridy++; 
      add(button, gbc); 
      gbc.gridy++; 
      add(new JButton("No Action Here"), gbc); 

      button.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        doButtonPressed(e); 
       } 

      }); 

      InputMap im = button.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
      ActionMap am = button.getActionMap(); 

      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaced"); 
      am.put("spaced", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        doButtonPressed(e); 
       } 

      }); 

     } 

     @Override 
     public void addNotify() { 
      super.addNotify(); 
      SwingUtilities.getRootPane(button).setDefaultButton(button); 
     } 

     protected void doButtonPressed(ActionEvent evt) { 
      count++; 
      label.setText("Pressed " + count + " times"); 
     } 

    } 

} 

Zakłada to oczywiście, że komponent z fokusem nie zużywa kluczowego zdarzenia (jak drugiego przycisku spożywającej przestrzeń lub wprowadzić klucze

0
switch(KEYEVENT.getKeyCode()){ 
     case KeyEvent.VK_ENTER: 
      // I was trying to use case 13 from the ascii table. 
      //Krewn Generated method stub... 
      break; 
} 
+2

Podczas gdy ten blok kodu może odpowiedzieć na pytanie, byłoby lepiej, gdybyś mógł podać wyjaśnienie, dlaczego tak się dzieje. – DavidPostill

-2

Najłatwiej byłoby zrobić ...

textBoxToEnterName.addActionListener(new ActionListener() 

... wiesz, co zrobić, stąd

+1

Nie, właściwie nie wiem, co robić. –

1

W klasie ActionListener można po prostu dodać

public void actionPerformed(ActionEvent event) { 
    if (event.getSource()==textField){ 
     textButton.doClick(); 
    } 
    else if (event.getSource()==textButton) { 
     //do something 
    } 
} 
0

bez ramy tego działa dla mnie:

JTextField tf = new JTextField(20); 
tf.addKeyListener(new KeyAdapter() { 

    public void keyPressed(KeyEvent e) { 
    if (e.getKeyCode()==KeyEvent.VK_ENTER){ 
     SwingUtilities.getWindowAncestor(e.getComponent()).dispose(); 
    } 
    } 
}); 
String[] options = {"Ok", "Cancel"}; 
int result = JOptionPane.showOptionDialog(
    null, tf, "Enter your message", 
    JOptionPane.OK_CANCEL_OPTION, 
    JOptionPane.QUESTION_MESSAGE, 
    null, 
    options,0); 

message = tf.getText(); 
0

wiem, że to nie jest najlepszy sposób, aby to zrobić, ale kliknij prawym przyciskiem myszy przycisk, zdarzenia, klucz, wpisane klawisze. Jest to prosty sposób na zrobienie tego, ale reaguje na każdy klucz