2011-11-17 41 views
10

Hành vi mặc định của JTable là thêm vào nội dung khi bạn bắt đầu nhập và đặt dấu nháy tại vị trí được nhấp khi nhấp vào. Tôi muốn hành vi của cả hai thứ này thay đổi, vì vậy nội dung được thay thế khi tôi chỉnh sửa ô, bằng cách nhập hoặc bằng cách nhấp và sau đó nhập. Khi tôi bấm vào một ô và sau đó thay đổi vị trí dấu mũ, tuy nhiên, tôi muốn nội dung ở lại để tôi có thể thay đổi nó.Làm thế nào để chọn tất cả văn bản trong ô JTable khi chỉnh sửa nhưng không phải khi gõ?

Tôi biết cách chọn tất cả khi ô trở thành chỉnh sửa, bằng cách thay thế trình chỉnh sửa ô có chọn tất cả bên trong SwingUtilities.invokeLater (xem elsewhere), nhưng điều đó làm cho hành vi nhập bị hỏng. Khi tôi làm điều này và bắt đầu nhập vào một ô, đầu tiên ký tự đã nhập được nối vào chuỗi, sau đó nó được chọn (nhưng lựa chọn là vô hình!) Và khi nhập một ký tự khác, nội dung sẽ được thay thế bằng ký tự đó.

Có cách nào thay thế nội dung ngay lập tức khi nhập vào ô được đánh dấu (nhưng không chỉnh sửa), nhưng chọn tất cả khi nhấp vào ô?

Đây là mã tôi sử dụng cho các CellEditor:

public class TextFieldCellEditor extends JTextField implements TableCellEditor 
{ 
    private CellEditorListener cellEditorListener = null; 

    private boolean    isInteger   = false; 
    private Object    oldValue; 

    // Start editing 
    @Override 
    public Component getTableCellEditorComponent(JTable table, Object obj, boolean isSelected, int row, int column) 
    { 
     Color color2 = DefaultLookup.getColor(this, ui, "Table.alternateRowColor"); 
     super.setBackground(color2 != null && (row & 1) == 1? color2 : table.getBackground()); 
     super.setForeground(table.getForeground()); 
     super.setBorder(DefaultLookup.getBorder(this, ui, "Table.focusCellHighlightBorder")); 

     super.setText(obj.toString()); 

     isInteger = obj instanceof Integer; 
     if (isInteger) 
     { 
      super.setHorizontalAlignment(SwingConstants.RIGHT); 
      oldValue = obj; 
     } 

     // SwingUtilities.invokeLater(new Runnable() 
     // { 
     // public void run() 
     // { 
     // TextFieldCellEditor.this.selectAll(); 
     // } 
     // }); 

     return this; 
    } 

    // Retrieve e dited value 
    @Override 
    public Object getCellEditorValue() 
    { 
     if (isInteger) 
     { 
      // Try to convert to integer. If input is invalid, revert. 
      try 
      { 
       return new Integer(super.getText()); 
      } 
      catch (NumberFormatException e) 
      { 
       return oldValue; 
      } 
     } 
     return super.getText(); 
    } 

    @Override 
    public boolean isCellEditable(EventObject e) 
    { 
     return true; 
    } 

    @Override 
    public boolean shouldSelectCell(EventObject e) 
    { 
     return true; 
    } 

    @Override 
    public boolean stopCellEditing() 
    { 
     cellEditorListener.editingStopped(new ChangeEvent(this)); 
     return true; 
    } 

    @Override 
    public void cancelCellEditing() 
    { 
     cellEditorListener.editingCanceled(new ChangeEvent(this)); 
    } 

    @Override 
    public void addCellEditorListener(CellEditorListener celleditorlistener) 
    { 
     cellEditorListener = celleditorlistener; 
    } 

    @Override 
    public void removeCellEditorListener(CellEditorListener celleditorlistener) 
    { 
     if (cellEditorListener == cellEditorListener) cellEditorListener = null; 
    } 
} 
+0

triển khai này không hợp lệ: a) không hỗ trợ thêm nhiều người nghe b) không thông báo cho người nghe của mình khi dừng/hủy vì lý do _internal_ (như nhập lần nhấn fi) Xem nguồn của DefaultCellEditor để biết ý tưởng cần thiết – kleopatra

+0

Than ks. Sửa lỗi. –

Trả lời

2

Thực hiện getTableCellEditorComponent() của bạn, thêm những điều sau đây:

if (isSelected) { 
    this.selectAll(); 
} 

Là một sang một bên, tại sao không mở rộng AbstractCellEditor hoặc DefaultCellEditor(JTextField textField)? Xem thêm How to Use Tables: Using Other Editors.

Phụ lục: Xem thêm Table Select All RendererTable Select All Editor.

+0

Cảm ơn. Tôi nghĩ rằng đó là chọn lựa sẽ luôn luôn đúng kể từ khi tôi điều hướng đến các tế bào, hoặc với bàn phím hoặc với chuột, vì vậy tôi bỏ qua nó. –

+0

Tôi đã thử nghiệm với việc mở rộng AbstractCellEditor trong quá khứ nhưng cuối cùng đã giải quyết vấn đề này. Dunno tại sao nữa. –

+0

Tôi hoán đổi nó một lần nữa vì người nghe (xem chú thích ở trên) và trường 'ui' được bảo vệ bên trong' JTextField', vì vậy đó là lý do tại sao tôi làm theo cách này. Địa ngục, tôi thậm chí không biết tại sao tôi sử dụng (như tôi phát hiện ra bây giờ) không khuyến khích lớp 'DefaultLookup' thay vì' UIManager' (có thể sao chép một số mã noob từ internet) –

0

Giải pháp sạch nhất tôi có thể tìm cho trường hợp này là để ghi đè lên editCellAt của JTable và thông báo cho CellEditor về cách chỉnh sửa đã được kích hoạt:

@Override 
public boolean editCellAt(int row, int column, EventObject e) { 
    cellEditor.setKeyTriggered(e instanceof KeyEvent); 
    return super.editCellAt(row, column, e); 
} 

Và đây là mã CellEditor liên quan:

public class MyCellEditor extends DefaultCellEditor { 

    private boolean keyTriggered; 

    public MyCellEditor() { 
     super(new JTextField()); 
     final JTextField textField = (JTextField) getComponent(); 
     textField.addFocusListener(new FocusAdapter() { 
      @Override 
      public void focusGained(FocusEvent e) { 
       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         if (!keyTriggered) { 
          textField.selectAll(); 
         } 
        } 
       }); 
      } 
     }); 
    } 

    public void setKeyTriggered(boolean keyTriggered) { 
     this.keyTriggered = keyTriggered; 
    } 

    @Override 
    public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) { 
     final JTextField textField = (JTextField) 
       super.getTableCellEditorComponent(table, value, isSelected, row, column); 
     textField.selectAll(); 
     return textField; 
    } 
} 
Các vấn đề liên quan