2012-05-13 49 views
2

我想在我的應用程序(Control + S)中的任何位置觸發保存操作。我已經添加了必要的鍵綁定,並按預期觸發了操作。但是,如果我在JTable上嘗試Control + 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一樣,我在運行代碼時沒有問題。您可能會尋找CellEditor,無意中擊敗editingStopped(),討論heresscce可能有助於澄清問題。

附錄:您可以取消編輯saveAction()處理程序,如下所示。

table.editingCanceled(null); 

僅供參考,我已經更新了你的例子在以下幾個方面:

代碼:

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的輸入/操作映射添加操作引用,或2)覆蓋editCellAt以返回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