2009-07-24 35 views
33

Tôi có một ứng dụng Java dành cho máy tính để bàn nhỏ sử dụng Swing. Có một hộp thoại nhập dữ liệu với một số lĩnh vực đầu vào của các loại khác nhau (JTextField, JComboBox, JSpinner, JFormattedTextField). Khi tôi kích hoạt JFormattedTextFields hoặc bằng cách duyệt qua biểu mẫu hoặc bằng cách nhấp vào nó bằng chuột, tôi muốn nó chọn tất cả văn bản mà nó hiện đang chứa. Bằng cách đó, người dùng chỉ có thể bắt đầu nhập và ghi đè các giá trị mặc định.Làm thế nào để chọn tất cả văn bản trong một JFormattedTextField khi nó được tập trung?

Tôi có thể làm như thế nào? Tôi đã sử dụng một FocusListener/FocusAdapter mà gọi selectAll() trên JFormattedTextField, nhưng nó không chọn bất cứ điều gì, mặc dù phương thức focusGained() của FocusAdapter được gọi (xem mẫu mã bên dưới).

private javax.swing.JFormattedTextField pricePerLiter; 
// ... 
pricePerLiter.setFormatterFactory(
    new JFormattedTextField.AbstractFormatterFactory() { 
    private NumberFormatter formatter = null; 
    public JFormattedTextField.AbstractFormatter 
     getFormatter(JFormattedTextField jft) { 
     if (formatter == null) { 
      formatter = new NumberFormatter(new DecimalFormat("#0.000")); 
      formatter.setValueClass(Double.class); 
     } 
     return formatter; 
    } 
}); 
// ... 
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() { 
    public void focusGained(java.awt.event.FocusEvent evt) { 
     pricePerLiter.selectAll(); 
    } 
}); 

Bất kỳ ý tưởng nào? Điều thú vị là việc chọn tất cả các văn bản của nó rõ ràng là hành vi mặc định cho cả JTextField và JSpinner, ít nhất là khi tabbing thông qua biểu mẫu.

Trả lời

65

Quấn cuộc gọi của bạn với SwingUtilities.invokeLater vì vậy nó sẽ xảy ra sau khi tất cả các sự kiện AWT cấp phát đã được xử lý:

pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() { 
    public void focusGained(java.awt.event.FocusEvent evt) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       pricePerLiter.selectAll(); 
      } 
     }); 
    } 
}); 
+3

Cảm ơn, đó là nó. Tôi chỉ có thể đoán rằng NumberFormatter đang làm một cái gì đó mà undoes selectAll()? –

+3

Vâng. Nó định dạng giá trị và đặt lại văn bản. –

+1

+1 Cần thiết này, không thể nhớ ngay lập tức làm thế nào để làm điều này tự của tôi, googled và ngay lập tức tìm thấy câu trả lời này. Cảm ơn! –

6

Thats vì JFormattedTextfield đè processFocusEvent để định dạng trên tập trung thu/tâm mất.

Một chắc chắn bắn cách là mở rộng JFormattedTextField và ghi đè lên các phương pháp processFocusEvent:

new JFormattedTextField("...") { 
     protected void processFocusEvent(FocusEvent e) { 
      super.processFocusEvent(e); 
      if (e.isTemporary()) 
       return; 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        selectAll(); 
       } 
      }); 
     } 
    }; 

Sử dụng một focusListener có thể không phải lúc nào work..since nó sẽ phụ thuộc vào thời gian mà tại đó nó được gọi là tương đối so với processFocusEvent .

14

Ngoài việc trên, nếu bạn muốn điều này cho tất cả các lĩnh vực văn bản mà bạn chỉ có thể làm:

KeyboardFocusManager.getCurrentKeyboardFocusManager() 
    .addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() 
{ 
    public void propertyChange(final PropertyChangeEvent e) 
    { 
     if (e.getNewValue() instanceof JTextField) 
     { 
      SwingUtilities.invokeLater(new Runnable() 
      { 
       public void run() 
       { 
        JTextField textField = (JTextField)e.getNewValue(); 
        textField.selectAll(); 
       } 
      }); 

     } 
    } 
}); 
2

Mã của camickr thể được cải thiện nhẹ. Khi tiêu điểm chuyển từ JTextField sang một loại thành phần khác (nút như vậy), lựa chọn tự động cuối cùng sẽ không bị xóa. Nó có thể được cố định theo cách này:

KeyboardFocusManager.getCurrentKeyboardFocusManager() 
     .addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() 
    { 
     @Override 
     public void propertyChange(final PropertyChangeEvent e) 
     { 

      if (e.getOldValue() instanceof JTextField) 
      { 
        SwingUtilities.invokeLater(new Runnable() 
        { 
          @Override 
          public void run() 
          { 
            JTextField oldTextField = (JTextField)e.getOldValue(); 
            oldTextField.setSelectionStart(0); 
            oldTextField.setSelectionEnd(0); 
          } 
        }); 

      } 

      if (e.getNewValue() instanceof JTextField) 
      { 
        SwingUtilities.invokeLater(new Runnable() 
        { 
          @Override 
          public void run() 
          { 
            JTextField textField = (JTextField)e.getNewValue(); 
            textField.selectAll(); 
          } 
        }); 

      } 
     } 
    }); 
7

Tôi biết đây là loại cũ, nhưng tôi đã đưa ra một giải pháp sạch hơn, mà không invokeLater:

private class SelectAllOfFocus extends FocusAdapter { 

    @Override 
    public void focusGained(FocusEvent e) { 
     if (! e.isTemporary()) { 
      JFormattedTextField textField = (JFormattedTextField)e.getComponent(); 
      // This is needed to put the text field in edited mode, so that its processFocusEvent doesn't 
      // do anything. Otherwise, it calls setValue, and the selection is lost. 
      textField.setText(textField.getText()); 
      textField.selectAll(); 
     } 
    } 

} 
+0

hoạt động đối với tôi trong mọi trường hợp +1 – mKorbel

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