为什么F6(或Ctrl-F6)开始编辑JTable?

时间:2014-04-29 18:06:42

标签: java swing jtable key-bindings

我想使用Ctrl-F6在JTable和相关的JTree之间切换。然而,Ctrl-F6启动JTable的单元格编辑器。 JTable只有一个默认的密钥监听器:javax.swing.ToolTipManager $ AccessibilityKeyListener ...但是删除它并没有解决问题。 所以我试图找出这是否是一个关键绑定以及它可能存在于哪里......所以我编写了这个简单的函数(在Jython中,但对于Java-ists应该是完全可理解的):

def print_comp_maps( comp, name ):    
    # list all task tree's system-set hotkeys
    # NB respective values here: 0, 1, 2
    input_map_conditions = [ JComponent.WHEN_FOCUSED, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, JComponent.WHEN_IN_FOCUSED_WINDOW ]
    input_map_names = [ "focused", "ancestor", "in focused window" ]

    print( "=== comp: %s" % name )
    for condition in input_map_conditions:
        print( "  === condition: %s" % input_map_names[ condition ])
        i_map = comp.getInputMap( condition )
        depth = 0
        while i_map:
            depth += 1
            print( "  %s=== imap %s:" % ( "  " * depth, i_map ))
            keys = i_map.keys()
            if keys:
                for keystroke in keys:
                    print( "  %s=== keystroke %s value %s" % ( "  " * ( depth + 1 ), keystroke, i_map.get( keystroke ) ) )
            i_map = i_map.parent

JTable的结果是:

=== comp: date_table
  === condition: focused
    === imap javax.swing.InputMap@1a8a84f:
  === condition: ancestor
    === imap javax.swing.InputMap@1c1edd9:
      === imap javax.swing.plaf.InputMapUIResource@e674b9:
        === keystroke ctrl pressed DOWN value selectNextRowChangeLead
        === keystroke shift pressed UP value selectPreviousRowExtendSelection
        === keystroke shift pressed INSERT value paste
        === keystroke ctrl pressed RIGHT value selectNextColumnChangeLead
        === keystroke shift ctrl pressed LEFT value selectPreviousColumnExtendSe
lection
        === keystroke shift pressed KP_UP value selectPreviousRowExtendSelection
        === keystroke pressed DOWN value selectNextRow
        === keystroke ctrl pressed UP value selectPreviousRowChangeLead
        === keystroke ctrl pressed LEFT value selectPreviousColumnChangeLead
        === keystroke pressed CUT value cut
        === keystroke pressed END value selectLastColumn
        === keystroke shift pressed PAGE_UP value scrollUpExtendSelection
        === keystroke pressed KP_UP value selectPreviousRow
        === keystroke shift ctrl pressed UP value selectPreviousRowExtendSelecti
on
        === keystroke ctrl pressed HOME value selectFirstRow
        === keystroke ctrl pressed INSERT value copy
        === keystroke shift pressed LEFT value selectPreviousColumnExtendSelecti
on
        === keystroke ctrl pressed END value selectLastRow
        === keystroke ctrl pressed PAGE_DOWN value scrollRightChangeSelection
        === keystroke shift ctrl pressed RIGHT value selectNextColumnExtendSelec
tion
        === keystroke pressed LEFT value selectPreviousColumn
        === keystroke ctrl pressed PAGE_UP value scrollLeftChangeSelection
        === keystroke pressed KP_LEFT value selectPreviousColumn
        === keystroke shift pressed KP_RIGHT value selectNextColumnExtendSelecti
on
        === keystroke pressed SPACE value addToSelection
        === keystroke ctrl pressed SPACE value toggleAndAnchor
        === keystroke shift pressed SPACE value extendTo
        === keystroke shift ctrl pressed SPACE value moveSelectionTo
        === keystroke shift ctrl pressed DOWN value selectNextRowExtendSelection
        === keystroke ctrl pressed BACK_SLASH value clearSelection
        === keystroke pressed ESCAPE value cancel
        === keystroke shift pressed DELETE value cut
        === keystroke shift pressed HOME value selectFirstColumnExtendSelection
        === keystroke pressed ENTER value selectNextRowCell
        === keystroke shift pressed ENTER value selectPreviousRowCell
        === keystroke pressed F8 value focusHeader
        === keystroke pressed RIGHT value selectNextColumn
        === keystroke shift ctrl pressed PAGE_UP value scrollLeftExtendSelection
        === keystroke shift pressed DOWN value selectNextRowExtendSelection
        === keystroke shift ctrl pressed KP_UP value selectPreviousRowExtendSele
ction
        === keystroke pressed PAGE_DOWN value scrollDownChangeSelection
        === keystroke shift pressed KP_LEFT value selectPreviousColumnExtendSele
ction
        === keystroke ctrl pressed X value cut
        === keystroke shift ctrl pressed PAGE_DOWN value scrollRightExtendSelect
ion
        === keystroke ctrl pressed SLASH value selectAll
        === keystroke ctrl pressed C value copy
        === keystroke ctrl pressed KP_RIGHT value selectNextColumnChangeLead
        === keystroke shift pressed END value selectLastColumnExtendSelection
        === keystroke shift ctrl pressed KP_DOWN value selectNextRowExtendSelect
ion
        === keystroke shift pressed TAB value selectPreviousColumnCell
        === keystroke ctrl pressed KP_LEFT value selectPreviousColumnChangeLead
        === keystroke pressed HOME value selectFirstColumn
        === keystroke ctrl pressed V value paste
        === keystroke pressed KP_DOWN value selectNextRow
        === keystroke ctrl pressed KP_DOWN value selectNextRowChangeLead
        === keystroke shift pressed RIGHT value selectNextColumnExtendSelection
        === keystroke ctrl pressed A value selectAll
        === keystroke shift ctrl pressed END value selectLastRowExtendSelection
        === keystroke pressed COPY value copy
        === keystroke ctrl pressed KP_UP value selectPreviousRowChangeLead
        === keystroke shift ctrl pressed KP_LEFT value selectPreviousColumnExten
dSelection
        === keystroke shift pressed KP_DOWN value selectNextRowExtendSelection
        === keystroke pressed TAB value selectNextColumnCell
        === keystroke pressed UP value selectPreviousRow
        === keystroke shift ctrl pressed HOME value selectFirstRowExtendSelectio
n
        === keystroke shift pressed PAGE_DOWN value scrollDownExtendSelection
        === keystroke pressed KP_RIGHT value selectNextColumn
        === keystroke shift ctrl pressed KP_RIGHT value selectNextColumnExtendSe
lection
        === keystroke pressed F2 value startEditing
        === keystroke pressed PAGE_UP value scrollUpChangeSelection
        === keystroke pressed PASTE value paste
  === condition: in focused window
    === imap javax.swing.ComponentInputMap@fa5f28:

...没有任何F6或Ctrl-F6键绑定的迹象......有没有人知道发生了什么?

顺便说一句,完全有可能将Ctrl-F6绑定添加到(例如)JTable" WHEN ANCESTOR OF ..." InputMap(例如,第一代,即上面列表中的javax.swing.InputMap@1c1edd9)。然后在Object中添加一个绑定,在ActionMap中添加一个Action。然后Ctrl-F6触发Action。但是,正如人们可能期望的那样,这绝不会抑制“开始编辑”。行动。神秘的奥秘是:这个结合位于哪个位置?我已经探索了JScrollPane(没有快乐,没有惊喜)甚至提交给DefaultCellEditor的构造函数的JTextField对象......(没有快乐,甚至更少惊喜)。难住了。有人知道绑定超级怪人吗?

甚至更晚

虽然Yarik解决了我仍然遇到问题的主要问题:当表格实现并且焦点以编程方式放在先前选择的行上时(即不使用鼠标),F2最初不起作用......它是只有在您导航(例如使用向上/向下键)之后,您才会发现F2开始编辑。 SSCCE说明了问题:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.lang.Runnable;
import javax.swing.*;


public class TableCellEditProb {
    public static void main(String args[]) {
        Runnable show_frame = new Runnable(){
            public void run(){
                JFrame main_frame = new JFrame( "F2 no effect on first realisation!");
                main_frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                final JTable table = new JTable( 5, 2 );
                table.setPreferredSize( new Dimension( 400, 200 ));
                table.setRowSelectionInterval( 2, 2 );
                table.putClientProperty("JTable.autoStartsEdit", false );      
                JPanel panel = new JPanel( new BorderLayout());
                AbstractAction button_action = new AbstractAction(){
                    public void actionPerformed(ActionEvent e){
                        System.out.println( "button pressed");
                        table.requestFocus();
                    }
                };
                button_action.putValue( AbstractAction.NAME, "Click (or press spacebar) to change focus to table..." );
                JButton button = new JButton( button_action );
                panel.add( table, BorderLayout.WEST );
                panel.add( button, BorderLayout.EAST );
                main_frame.getContentPane().add( panel );
                main_frame.pack();
                button.requestFocus();
                main_frame.setVisible( true );
            }
        };
        java.awt.EventQueue.invokeLater( show_frame );
    }
}

1 个答案:

答案 0 :(得分:2)

默认操作< - >键由InputMap和ActionMap中的L& F定义 我相信他们在任何外部听众面前被召唤。 你总是可以覆盖它。

或者,您可以覆盖 processKeyBinding

以下是可能满足您需求的代码示例。 它拦截Cntrl-F6并打印到sysout。

请参阅我的评论,为什么Cntrl-F6不在绑定中。

公共类PrintTableTest {

public JPanel buildUI() {
    String[] columnNames = {"First Name",
            "Last Name",
            "Sport",
            "# of Years",
            "Vegetarian"};

    Object[][] data = {
            {"Mary", "Campione",
                    "Snowboarding", 5, new JComboBox(new Object[]{Boolean.TRUE, Boolean.FALSE})},
            {"Alison", "Huml",
                    "Rowing", 3, Boolean.FALSE},
            {"Kathy", "Walrath",
                    "Knitting", 2, Boolean.FALSE},
            {"Sharon", "Zakhour",
                    "Speed reading", 20, Boolean.TRUE},
            {"Philip", "Milne",
                    "Pool", 10, Boolean.TRUE
            }
    };


    final JTable table = new JTable(increase(data, 50), columnNames);
    JScrollPane scrollPane = new JScrollPane(table);
    JButton print = new JButton("Print");
    print.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try {
                table.print();
            } catch (PrinterException e1) {
                e1.printStackTrace();
            }
        }
    });

    table.setDefaultRenderer(TableColumn.class, new TableCellRenderer());
    JPanel panel = new JPanel(new BorderLayout(5, 5));
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.add(print, BorderLayout.SOUTH);
    JTextField textField = new JFormattedTextField();
    JSpinner spinner = new JSpinner(new SpinnerNumberModel());
    spinner.setEditor(textField);
    textField.setEditable(false);
    panel.add(spinner, BorderLayout.NORTH);


    panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F6, InputEvent.CTRL_DOWN_MASK), "doSomething" );
    panel.getActionMap().put("doSomething",new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("TEST OUT");
        }
    });
    table.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
    return panel;
}

private Object[][] increase(Object[][] src, int times) {

    Object[][] out = new Object[src.length * times][];
    for (int i = 0; i < times; i++) {
        System.arraycopy(src, 0, out, i * src.length, src.length);
    }
    return out;
}

public JFrame getFrame(String name) {
    JFrame frame = new JFrame(name);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setContentPane(buildUI());
    frame.setSize(200, 200);
    frame.pack();

    return frame;

}

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

        public void run() {
            PrintTableTest ui = new PrintTableTest();
            JFrame frame = ui.getFrame("TABLE PRINT TEST");
            frame.setVisible(true);
        }
    });
}

private class TableCellRenderer extends DefaultTableCellRenderer {

    /**
     * Returns the default table cell renderer.
     *
     * @param table      the <code>JTable</code>
     * @param value      the value to assign to the cell at <code>[row, column]</code>
     * @param isSelected true if cell is selected
     * @param hasFocus   true if cell has focus
     * @param row        the row of the cell to render
     * @param column     the column of the cell to render
     * @return the default table cell renderer
     */
    public Component getTableCellRendererComponent(JTable table,
                                                   Object value,
                                                   boolean isSelected,
                                                   boolean hasFocus,
                                                   int row,
                                                   int column) {
        if (value instanceof JComboBox) {
            return (Component) value;
        }
        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

    }
}

}