2013-01-01 32 views
0

我有一個JTextField的JPanel,我想實現waitForTextFieldSpace。我認爲製作一個自定義JTextField將是最優雅的解決方案,但我不完全確定。等待JTextField「SPACE」事件

public class MyPanel { 
    JTextField textField; 

    //...constructor, methods, etc 

    public void waitForTextFieldSpace() { 
     //...don't return until the user has pressed space in the text field 
    } 
} 

我確實有一些代碼,有一個JFrame等待空格鍵。但我不知道如何執行上面的文本字段任務。

public void waitForKey(final int key) { 
     final CountDownLatch latch = new CountDownLatch(1); 
     KeyEventDispatcher dispatcher = new KeyEventDispatcher() { 
      public boolean dispatchKeyEvent(KeyEvent e) { 
       if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == key) { 
        latch.countDown(); 
       } 
       return false; 
      } 
     }; 
     KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(dispatcher); 
     try { 
      //current thread waits here until countDown() is called (see a few lines above) 
      latch.await(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(dispatcher); 

    } 
+0

這不是Swing的工作原理。所有Swing事件都在單個線程中調度,如果因任何原因阻止該線程,則不能再分派事件。當你想要的密鑰被觸發時,你最好的選擇是使用監聽器觸發一個方法 – MadProgrammer

回答

0

正確的解決方案是創建定製的JTextField如下

public class MyTextField extends JTextField { 

    private static final long serialVersionUID = 1833734152463502703L; 

    public MyTextField() { 

    } 

    public void waitForKey(final int key) { 
     final CountDownLatch latch = new CountDownLatch(1); 
     KeyEventDispatcher dispatcher = new KeyEventDispatcher() { 
      public boolean dispatchKeyEvent(KeyEvent e) { 
       if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == key) { 
        latch.countDown(); 
       } 
       return false; 
      } 
     }; 
     KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(dispatcher); 
     try { 
      //current thread waits here until countDown() is called (see a few lines above) 
      latch.await(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(dispatcher); 

    } 

} 

,然後在原來的方法,只是將myTextField對象調用WAITFORKEY()

+0

這不會鎖定EDT渲染該方法無用嗎? – MadProgrammer

0

您是否使用Key Event Listener查看過?您可以將其添加到您的文本字段或區域,並檢查它是否有特定的鍵。我將它用於諸如enter或tab之類的東西,這樣當用戶按下它時,它會啓動一個不同的動作。

Java Key Listener

請問

爲您的文檔偵聽器的工作?每當文本字段中的值發生更改時都會進行檢查。

Document Listener

這裏是我所做的文本字段時按下某個鍵採取行動,一些示例代碼。

textField.addKeyListener(new java.awt.event.KeyAdapter() { 
    public void keyPressed(final java.awt.event.KeyEvent evt) { 
     textFieldKeyPressed(evt); 
    } 
}); 

private void textFieldKeyPressed(final java.awt.event.KeyEvent evt) { 
    final int key = evt.getKeyCode(); 
    if (key == KeyEvent.VK_ENTER || key == KeyEvent.VK_TAB) { 
     if (!textField.getText().equals("Updating")) { 
      loadTable(); 
     } 
    } 
} 
+0

是的,但是這並不會阻止我在SPACE上返回方法。我對KeyListener非常熟悉,但是我需要創建上面看到的那個方法... – CodeGuy

+0

我想我不確定你在這裏有什麼。你有一個框架或一個主框架與第二個窗口打開? – Logan

4
  • 永不使用Keylistener(沒有真實原因,例如以確定3個或更多個按鍵是按下的)JTextComponets,使用Document,DocumentListener,DocumentFilter

  • 鍵綁定使用標準鍵,通知 - 必須檢查API

  • 中實現,如果沒有所需的密鑰(key_shortcut)在這種情況下使用DocumentFilterPatern

簡單示例

import java.awt.*; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.regex.Pattern; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.text.*; 

public class TextAreaTest extends JFrame { 

    private static final long serialVersionUID = 1L; 
    private JTextArea textArea; 

    public TextAreaTest() { 
     textArea = new JTextArea(); 
     textArea.setPreferredSize(new Dimension(60, 32)); 
     textArea.setOpaque(true); 
     textArea.setLineWrap(true); 
     textArea.setWrapStyleWord(true); 
     ((AbstractDocument) textArea.getDocument()).setDocumentFilter(new DocumentFilter() { 

      @Override 
      public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { 
       //string = string.replaceAll("\\{", "\\{}"); 
       super.insertString(fb, offset, string, attr); 
      } 

      @Override 
      public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 
       if (Pattern.compile("\\p{Space}").matcher(text).find()) { 
        System.exit(0); 
       } 
       //text = text.replaceAll("\\{", "\\{}"); 
       super.replace(fb, offset, length, text, attrs); 
      } 
     }); 

     textArea.getDocument().addDocumentListener(new DocumentListener() { 

      @Override 
      public void changedUpdate(DocumentEvent e) { 
       update(e); 
      } 

      @Override 
      public void insertUpdate(DocumentEvent e) { 
       update(e); 
      } 

      @Override 
      public void removeUpdate(DocumentEvent e) { 
       update(e); 
      } 

      private void update(DocumentEvent e) { 
       List<String> lines = getLines(textArea); 
       String lastLine = lines.get(lines.size() - 1); 
       int tabbedTextWidth = Utilities.getTabbedTextWidth(new Segment(
         lastLine.toCharArray(), 0, lastLine.length()), textArea.getFontMetrics(textArea.getFont()), 0, null, 0); 
       int lineHeight = getLineHeight(textArea); 
       if (lines.size() * lineHeight > textArea.getHeight() || tabbedTextWidth > textArea.getWidth()) { 
        System.out.println("Too big! Should refuse the update!"); 
       } 
      } 
     }); 
     getContentPane().add(textArea); 
    } 

    private static List<String> getLines(JTextArea textArea) { 
     int lineHeight = getLineHeight(textArea); 
     List<String> list = new ArrayList<String>(); 
     for (int num = 0;; num++) { 
      int i = textArea.viewToModel(new Point(0, num * lineHeight)); 
      int j = textArea.viewToModel(new Point(0, (num + 1) * lineHeight)); 
      if (i == 0 && j == 0) { 
       continue; 
      } 
      if (textArea.getDocument().getLength() == i && i == j) { 
       break; 
      } 
      String s = removeTrailingNewLine(textArea.getText().substring(i, j)); 
      list.add(s); 
      //System.out.println(i + " " + j + " = " + s); 
     } 
     return list; 
    } 

    private static int getLineHeight(JTextArea textArea) { 
     return textArea.getFontMetrics(textArea.getFont()).getHeight(); 
    } 

    private static String removeTrailingNewLine(String s) { 
     if (s.endsWith("\n")) { 
      return s.substring(0, s.length() - 1); 
     } else { 
      return s; 
     } 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       TextAreaTest test = new TextAreaTest(); 
       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       test.pack(); 
       test.setVisible(true); 
      } 
     }); 
    } 
} 
+1

DocumentListener的+1 – Reimeus