3

アプリケーションの任意の場所で保存アクションをトリガーしたい(Control + S)。必要なキーバインディングを追加しました。アクションは期待どおりにトリガーされます。ただし、JTableでControl + Sを試してみると、テーブルはカスタムアクションを開始し、編集のためにテーブルセルをアクティブにします。テーブルの入力マップで編集アクションを無効にしたと思います。ここで何が欠けていますか?

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;
    }   
}
4

3 に答える 3

4

@Guillaumeのように、私はあなたのコードを実行するのに問題はありませんでした。ここで説明されているCellEditor、うっかりして敗北したものを探すかもし​​れません。sscceは、問題を明確にするのに役立つ場合がありますeditingStopped()

補遺:saveAction()以下に示すように、ハンドラーでの編集をキャンセルできます。

table.editingCanceled(null);

参考までに、いくつかの点であなたの例を更新しました。

  • Control-SJTable Action一般的なルックアンドフィールの実装にバインドされていないため、削除する必要はありません。
  • クロスプラットフォームの利便性のために、を使用してgetMenuShortcutKeyMask()ください。
  • Swing GUIオブジェクトは、イベントディスパッチスレッドでのみ構築および操作する必要があります。

コード:

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;
    }
}
于 2012-05-13T22:35:50.233 に答える
2

私はついにそれを理解しました。設定するキーバインディングはありません。アクションマップは存在しません。したがって、putの呼び出しは何もしていませんでした。

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に渡します。これを回避するには2つの方法があります。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);                
        }
于 2012-05-14T01:08:30.190 に答える
0

左/右のキーを再割り当てしたいという同様のケースがありました。私を助けたのはhttps://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.htmlを見たことです

最後に私はこのようなコードを思いついた:

    {
        InputMap im = jTable1.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "decStash");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "incStash");
    }
    {
        InputMap im = jTable1.getInputMap(JComponent.WHEN_FOCUSED);
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "decStash");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "incStash");
    }
    {
        ActionMap am = jTable1.getActionMap();
        am.put("decStash", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                log.debug("decStash");
            }
        });
        am.put("incStash", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                log.debug("incStash");
            }
        });
    }

私のコードは、選択した回答のようにルートコンポーネントを検索しないことに注意してください。

于 2021-12-13T07:15:10.980 に答える