Java 为什么F6(或Ctrl-F6)开始编辑JTable?
我想使用Ctrl-F6在JTable和关联的JTree之间切换。但是,Ctrl-F6会启动JTable的单元格编辑器。JTable只有一个默认键侦听器:javax.swing.ToolTimManager$AccessibilityKeyListener。。。但是移除这个并不能解决问题。 所以我试图找出这是否是一个键绑定,以及它可能驻留在哪里。。。因此,我编写了这个简单的函数(用Jython编写,但Java开发者应该可以完全理解): JTable的结果如下:Java 为什么F6(或Ctrl-F6)开始编辑JTable?,java,swing,jtable,key-bindings,Java,Swing,Jtable,Key Bindings,我想使用Ctrl-F6在JTable和关联的JTree之间切换。但是,Ctrl-F6会启动JTable的单元格编辑器。JTable只有一个默认键侦听器:javax.swing.ToolTimManager$AccessibilityKeyListener。。。但是移除这个并不能解决问题。 所以我试图找出这是否是一个键绑定,以及它可能驻留在哪里。。。因此,我编写了这个简单的函数(用Jython编写,但Java开发者应该可以完全理解): JTable的结果如下: === comp: date_tab
=== 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祖先…”InputMap(例如,第一代,即javax.swing)中。InputMap@1c1edd9在上面的列表中)。然后在那里的对象和ActionMap中的动作之间添加绑定。Ctrl-F6然后启动该操作。但是,正如人们可能预期的那样,这绝不会阻止“启动”行动。神秘的奥秘在于:费金在哪里???我已经研究了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 );
}
}
默认操作键由InputMap和ActionMap中的L&F定义
我相信他们是在任何外部听众面前被呼叫的。
您可以随时覆盖它
或者,您可以覆盖processKeyBinding
下面是一个代码示例,它可以执行您需要的操作。
它截取Cntrl-F6并打印到sysout
关于Cntrl-F6不在绑定中的原因,请参阅我的评论
公共类打印表测试{
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);
}
}
}如引用的关键绑定文章所示,许多L&F将
F2
绑定到startEditing
。。。我知道F2是。。。如果您愿意查看,它将显示在输入地图的列表中!但是我的问题是关于Ctrl-F6,你有没有尝试过这个问题的解决方案:我非常关心的不仅是看,而且还引用了一篇有用的文章;不客气。我看到com.apple.laf.AquaLookAndFeel
绑定了F6
,也许是为了避免冲突。@trashgod thanx-我认为这是一个Windows框,特别是Windows 7。。。另外,我没有使用Apple L&F。谢谢,但是只有知道在哪里可以找到将击键绑定到对象的InputMap(对象然后绑定到ActionMap中的操作),才能覆盖某些内容。我的问题是我找不到输入映射。这也意味着我不能删除绑定。默认值应该在JTable UI委托中,因此请检查源代码。您仍然可以覆盖JTable.processKeyBundings。如果我在editCellAt()上放置一个断点,堆栈跟踪将显示路径。顺便说一句,在调试代码一段时间后,我可以看到Ctrl-F6没有任何意义。任何按下的键都会触发编辑,只是碰巧这些键不会生成可打印的字符。用F7或F8尝试相同的方法。简而言之,覆盖processKeyBinding,添加操作并添加客户机属性table.putClientProperty(“JTable.autoStartsEdit”,Boolean.FALSE);这样做的副作用是不使用任何键开始编辑-只要您可以使用它即可:-)@kleopatra F2仍然有效,因为它包含在InputMap列表中(请参见上文)。同样毫无疑问,人们可以在JTable上放置一个KeyListener,它将开始编辑所有实际打印内容的键。在我看来,这应该是autoStartsEdit=True的默认行为……除F2之外的任何键,你都是挑剔者——这通常是我的角色:-)根据设计,由编辑器决定是否要开始(或继续,fwim)对特定击键的编辑,表在其中没有太多的作用。因此,您可以尝试相应地实现它的isCellEditable(EventObject)——这不是完全不重要的,因为有几个原因(与表一样,编辑器对editingComponent的内部结构不太了解:textField没有公共api来决定给定的按键是否会产生有效的键入键)
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);
}
}