2012-05-13 5 views
2

내 응용 프로그램 (Control + S)에서 저장 작업을 트리거하려고합니다. 필요한 키 바인딩을 추가하고 작업이 예상대로 트리거됩니다. 그러나 JTable에서 Ctrl + S를 누르면 테이블이 사용자 정의 액션을 시작하고 편집을 위해 테이블 ​​셀을 활성화합니다. 테이블의 입력 맵에서 편집 작업을 비활성화 한 것 같습니다. 내가 여기서 무엇을 놓치고 있니?JTable 키 바인딩

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.KeyStroke; 
import javax.swing.UIManager; 

public class TestTableKeyBinding extends JFrame{ 

JTable table; 
JScrollPane scroll; 

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

TestTableKeyBinding(){ 
    super(); 
    initUI(); 
    addKeyBindings(); 
} 

void initUI(){ 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    String[] headers = new String[]{"apples", "bananas"}; 
    String[][] data = new String[][]{{"1", "2"},{"4","6"}}; 
    table = new JTable(data, headers); 
    table.setCellSelectionEnabled(true); 
    scroll = new JScrollPane(); 
    scroll.setViewportView(table); 
    this.add(scroll); 
    this.pack(); 
    this.setSize(new Dimension(300, 400)); 

} 

void addKeyBindings(){ 
    //root maps 
    InputMap im = this.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
    ActionMap am = this.getRootPane().getActionMap(); 

    //add custom action 
    im.put(KeyStroke.getKeyStroke("control S"), "save"); 
    am.put("save", saveAction()); 

    //disable table actions via 'none' 
    table.getInputMap().put(KeyStroke.getKeyStroke("control S"), "none"); 
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control S"), "none"); 
    table.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("control S"), "none"); 
    table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control S"), "none"); 
    ((InputMap)UIManager.get("Table.ancestorInputMap")).put(KeyStroke.getKeyStroke("control S"), "none"); 
} 

AbstractAction saveAction(){ 
    AbstractAction save = new AbstractAction(){ 
     public void actionPerformed(ActionEvent e) { 
      // TODO Auto-generated method stub 
       JOptionPane.showMessageDialog(TestTableKeyBinding.this.table, "Action Triggered."); 
     }   
    }; 
     return save; 
    } 
} 
+0

이 코드를 Win7 JDK1.6에서 실행하는 데 문제가 없습니다. –

+0

@Guillaume 테이블 셀을 선택한 후 'Ctrl + S'를 누르면 문제가 발생합니다. 동작이 트리거되고 선택한 셀이 편집을 시작합니다. – kirbs

답변

4

@Guillaume처럼 코드 실행에 문제가 없습니다. 의도하지 않게 editingStopped()을 패배시킨 CellEditor을 찾고 here을 살펴볼 수 있습니다. sscce은 문제를 명확히하는 데 도움이 될 수 있습니다.

부록 : 아래와 같이 saveAction() 처리기에서 편집을 취소 할 수 있습니다.

table.editingCanceled(null); 

는 참고로, 나는 몇 가지 측면에서 예를 업데이트했습니다

  • 제어-S &가 구현을 느껴 일반적인 찾는 모든 JTableAction에 바인딩, 그래서 필요에가 없습니다되지 않는다 remove입니다.
  • 플랫폼 간 편의성을 위해 getMenuShortcutKeyMask()을 사용하십시오.
  • 스윙 GUI 객체를 구성하고 조작해야합니다. event dispatch thread 만 있습니다.

코드 :

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.KeyStroke; 

public class TestTableKeyBinding extends JFrame { 

    private static final int MASK = 
     Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); 
    private JTable table; 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       TestTableKeyBinding test = new TestTableKeyBinding(); 
       test.setVisible(true); 
      } 
     }); 
    } 

    TestTableKeyBinding() { 
     super(); 
     initUI(); 
     addKeyBindings(); 
    } 

    private void initUI() { 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     String[] headers = new String[]{"apples", "bananas"}; 
     String[][] data = new String[][]{{"1", "2"}, {"4", "6"}}; 
     table = new JTable(data, headers); 
     table.setCellSelectionEnabled(true); 
     this.add(new JScrollPane(table)); 
     this.pack(); 
     this.setSize(new Dimension(300, 400)); 

    } 

    private void addKeyBindings() { 
     //root maps 
     InputMap im = this.getRootPane().getInputMap(
      JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
     ActionMap am = this.getRootPane().getActionMap(); 
     //add custom action 
     im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, MASK), "save"); 
     am.put("save", saveAction()); 
    } 

    private AbstractAction saveAction() { 
     AbstractAction save = new AbstractAction() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JOptionPane.showMessageDialog(
        TestTableKeyBinding.this.table, "Action Triggered."); 
       table.editingCanceled(null); 
      } 
     }; 
     return save; 
    } 
} 
+2

감사! 'table.editingCancelled (null)'은 제가 찾고있는 것입니다. – kirbs

+0

대단히 고마워,이 솔루션은 또한 나를 위해 잘 작동 – user489041

1

나는 마침내 그것을 알아 냈어. 설정된 키 바인딩이 없으므로 동작 맵이 존재하지 않습니다. 그래서 두는 부름은 아무 것도하지 않았습니다.

table.getInputMap().put(KeyStroke.getKeyStroke("control S"), "none"); 
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control S"), "none"); 
table.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("control S"), "none"); 
table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control S"), "none"); 
((InputMap)UIManager.get("Table.ancestorInputMap")).put(KeyStroke.getKeyStroke("control S"), "none"); 

JTable는, 편집 할 수 있도록 테이블을 트리거하여이 editCellAt에 키 이벤트를 전달합니다. 이 문제를 해결하는 데는 두 가지 방법이 있습니다. 1) JTable의 입력/액션 맵에 액션 참조를 추가하거나, editCellAt를 오버라이드 (override) 해 false를 돌려줍니다. 문제를 해결하는 방법은 다음과 같습니다.

public boolean editCellAt(int row, int column, EventObject e){    
      if(e instanceof KeyEvent){ 
       int i = ((KeyEvent) e).getModifiers(); 
       String s = KeyEvent.getModifiersExText(((KeyEvent) e).getModifiers()); 
       //any time Control is used, disable cell editing    
       if(i == InputEvent.CTRL_MASK){ 
        return false; 
       } 
      }    
      return super.editCellAt(row, column, e);     
     } 
+0

귀하의 질문에 대한 명확한 이해를 바탕으로, 나는 다른 접근법을 [여기에] 나타냈다. (http://stackoverflow.com/a/10575771/230513). – trashgod