2016-12-07 11 views
1

Я написал обычай DefaultCellEditor, чтобы при вводе в столбце length примера JTable я не могу ничего вводить, кроме цифр.Стоп JTable доступен для редактирования только при фокусировке и нажатии клавиши

Для этого я добавил KeyListener в JTextField, который используется в качестве компонента редактора. Хотя это отлично работает, если вы дважды щелкните по ячейке, чтобы изменить значение, это не сработает, если вы нажмете на ячейку один раз, а затем начнете вводить текст.

Как я могу запретить пользователю редактировать ячейку, если они нажимают на ячейку один раз, а затем начинают печатать, в то же время позволяя пользователю дважды щелкнуть по ячейке, чтобы начать ее редактирование?

import java.awt.Color; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.lang.reflect.Constructor; 

import javax.swing.DefaultCellEditor; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.border.LineBorder; 

@SuppressWarnings("serial") 
public class JTableTest extends JFrame { 
    private JTableTest() { 
     super("JTable Test"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLayout(new GridLayout(1, 1)); 
     createPanel(); 
     pack(); 
     setVisible(true); 
    } 

    JPanel panel = new JPanel(new GridLayout(1, 1)); 
    JScrollPane scroll; 

    private void createPanel() { 
     Object[] headers = {"Length", "Title"}; 
     Object[][] sampleData = {{"673", "Bat Outta Hell"}, 
       {"358", "Spanish Train"}, 
       {"673", "Bat Outta Hell"}}; 
     JTable table = new JTable(sampleData, headers); 
     table.setDefaultEditor(Object.class, new NumEditor()); 
     scroll = new JScrollPane(table); 
     panel.add(scroll); 
     getContentPane().add(panel); 
    } 

    private class NumEditor extends DefaultCellEditor { 
     Class<?>[] argTypes = new Class<?>[]{String.class}; 
     Constructor<?> constructor; 
     Object value; 

     public NumEditor() { 
      super(new JTextField()); 
      getComponent().setName("Table.editor"); 
     } 

     public boolean stopCellEditing() { 
      String s = (String)super.getCellEditorValue(); 
      try { 
       if ("".equals(s)) { 
        if (constructor.getDeclaringClass() == String.class) { 
         value = s; 
        } 
        return super.stopCellEditing(); 
       } 
       value = constructor.newInstance(new Object[]{s}); 
      } 
      catch (Exception e) { 
       ((JComponent)getComponent()).setBorder(new LineBorder(Color.red)); 
       return false; 
      } 
      return super.stopCellEditing(); 
     } 

     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
      this.value = null; 
      ((JComponent)getComponent()).setBorder(new LineBorder(Color.black)); 
      try { 
       Class<?> type = table.getColumnClass(column); 

       if (type == Object.class) { 
        type = String.class; 
       } 

       KeyListener kL = new KeyListener() { 
        public void keyPressed(KeyEvent e) { 

        } 
        public void keyReleased(KeyEvent e) { 

        } 
        public void keyTyped(KeyEvent e) { 
         char c = e.getKeyChar(); 
         if(Character.isDigit(c)){ 

         } else { 
          e.consume(); 
         } 
        } 
       }; 

       if(column == 0) 
        ((JComponent)getComponent()).addKeyListener(kL); 
       else 
        ((JComponent)getComponent()).removeKeyListener(kL); 

       constructor = type.getConstructor(argTypes); 
      } 
      catch (Exception e) { 
       return null; 
      } 
      return super.getTableCellEditorComponent(table, value, isSelected, row, column); 
     } 

     public Object getCellEditorValue() { 
      return value; 
     } 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> new JTableTest()); 
    } 
} 

ответ

2

Посмотрите на CellEditor.isCellEditable(EventObject anEvent). AbstractCellEditor и DefaultCellEditor реализовать интерфейс CellEditor.

Вы можете переопределить этот метод, чтобы вернуть значение false, если EventObject является экземпляром типа KeyEvent. В противном случае верните super.isCellEditable(anEvent).

+0

Это было действительно очень просто. Спасибо за помощь – Dan

+0

Добро пожаловать @Dan =) –

+0

Просто быстрый вопрос. Вы не знаете, почему «KeyListener» не удаляется, когда я использую другой столбец? – Dan

1

Ссылаясь на TT.'sanswer и используя DefaultCellEditor как оригинальный вопрос делает это так же просто, как добавить этот метод в DefaultCellEditor.

public boolean isCellEditable(EventObject anEvent) { 
    if (anEvent instanceof MouseEvent) { 
     return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart; 
    } 
    return false; 
} 
3

Stop JTable быть редактируемым только тогда, когда сфокусированы и нажата клавиша

Ну, это поведение по умолчанию при редактировании ячейки с строковыми данными.

Почему при попытке ввода числовых данных это должно быть другим?

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

Не нужно писать пользовательский редактор. Просто используйте JFormattedTextField в качестве редактора вместо JTextField:

Что-то вроде.

MaskFormatter format = new MaskFormatter("######"); 
JFormattedTextField ftf = new JFormattedTextField(format); 
DefaultCellEditor dce = new DefaultCellEditor(ftf); 
table.getColumnModel().getColumn(2).setCellEditor(dce); 
+0

Спасибо за ответ. Это полезно знать – Dan