JTable 编辑器中的键绑定
Key binding in JTable editor
我找到了与此类似的键绑定主题 (JTable Key Bindings)。我了解到它的键绑定绑定到 table 而不是编辑器。
我的目标是在编辑器上以 VK-ENTER 结尾的任何输入,它执行操作 pindah(添加新行并设置光标在新行上闪烁)。对不起,我没能从那个例子中吸取教训。
有办法吗?
这是我的代码(不包括导入,因为 Eclipse 会自动建议):
public class Fpos extends JFrame
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
Fpos frame = new Fpos();
frame.setVisible(true);
frame.setLocationRelativeTo(null); //make frame center of screen
} catch (Exception e) {e.printStackTrace();}
}
});
}
public Fpos()
{
//create Jpanel
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(10, 10, 1300, 700);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
//create label TOTAL
JLabel lblTotal = new JLabel("TOTAL : Rp.");
lblTotal.setFont(new Font("Wide Latin", Font.PLAIN, 30));
lblTotal.setBounds(33, 25, 312, 31);
contentPane.add(lblTotal);
//create label Total Amount
JLabel lblNewLabel = new JLabel("123,456,789");
lblNewLabel.setHorizontalAlignment(SwingConstants.RIGHT);
lblNewLabel.setFont(new Font("Wide Latin", Font.PLAIN, 60));
lblNewLabel.setBounds(583, 19, 659, 61);
contentPane.add(lblNewLabel);
//create jtable in scrollpane
String[] columnNames = {"PLU", "NAME", "UOM", "QTY", "PRICE","AMOUNT"};
Object[][] data = {{"", "", "", "", "", ""}};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model);
table.setFont(new Font("Tahoma", Font.PLAIN, 20));
table.setRowHeight(25);
JScrollPane sp=new JScrollPane(table);
sp.setBounds(25,100,1240,556);
contentPane.add(sp);
//set column width
TableColumnModel columnModel = table.getColumnModel();
short a[] = {150,540,50,150,150,200};
for(byte i=0;i<6;i++) { columnModel.getColumn(i).setPreferredWidth(a[i]); }
//render column format left alignment
for(byte i=0;i<3;i++) {table.getColumnModel().getColumn(i).setCellRenderer(new TextTableCellRenderer());}
//render column format ###,##0 right alignment
for(byte i=3;i<6;i++) {table.getColumnModel().getColumn(i).setCellRenderer(new NumberTableCellRenderer());}
//make cursor blinking on selected cell + select all cell value
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
table.changeSelection(0, 0, false, false);
if (table.editCellAt(0, 0))
{
Component editor = table.getEditorComponent();
editor.setFont(new Font("Tahoma", Font.PLAIN, 20));
editor.requestFocusInWindow();
((JTextComponent)editor).selectAll(); //select all cell value
//key binding
Action pindah = new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
//add row at last row
model.addRow(data);
//i want to add new blank row but somehow there is value on column 0, so I have to set it blank. If you have a solution on this, you're very welcome
model.setValueAt("", model.getRowCount()-1, 0);
//make cursor blinking on selected cell + select all cell value
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
table.changeSelection(0, 0, false, false);
if (table.editCellAt(model.getRowCount()-1, 0))
{
Component editor = table.getEditorComponent();
editor.setFont(new Font("Tahoma", Font.PLAIN, 20));
editor.requestFocusInWindow();
((JTextComponent)editor).selectAll(); //select all cell value
}
}
});
}
};
((JComponent) editor).getInputMap().put(KeyStroke.getKeyStroke((char) KeyEvent.VK_ENTER), "pindah");
((JComponent) editor).getRootPane().getActionMap().put("pindah", pindah);
}
}
});
}
// render column format left alignment
public class TextTableCellRenderer extends DefaultTableCellRenderer
{public TextTableCellRenderer() {{setHorizontalAlignment(JLabel.LEFT);}} }
// render column format to ###,##0
public class NumberTableCellRenderer extends DefaultTableCellRenderer
{
public NumberTableCellRenderer() {setHorizontalAlignment(JLabel.RIGHT);}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (value instanceof Number) {value = NumberFormat.getNumberInstance().format(value);}
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
不是答案,而是对您的代码的一些评论。
首先您需要了解事件调度线程 (EDT)。需要在 EDT 上更新 GUI 组件。
通常您不需要继续嵌套 SwingUtilities.invokeLater() 代码,因为您确实在 EDT 上创建了 GUI。
我们需要添加 invokeLater(...)
来制作第一个单元格 editable 并让光标闪烁的原因是,如果框架不可见,您将无法在组件上设置焦点.因此 invokeLater(...)
允许我们将代码添加到 EDT 的末尾,以便它在 main() 方法中的 setVsible(...) 语句之后执行。
因此,如果您确实想使用键绑定,您可以在 Fpos 的构造函数中设置所有键绑定 class。
但是,我不知道当前要求的正确解决方案。
目前,ActionListener 添加到用作单元格编辑器的 JTextField。当您按下 Enter 键时,将调用侦听器并调用 table 的 stop cell editing logic
,这意味着将编辑器中的值添加到 TableModel 并从 [=33] 中删除单元格编辑器=].
因此您不能简单地向编辑器添加键绑定,因为您需要发生此默认行为。
我想您可以创建自定义单元格编辑器。然后在 ActionListener 中,您可以添加其他要求。
我找到了与此类似的键绑定主题 (JTable Key Bindings)。我了解到它的键绑定绑定到 table 而不是编辑器。
我的目标是在编辑器上以 VK-ENTER 结尾的任何输入,它执行操作 pindah(添加新行并设置光标在新行上闪烁)。对不起,我没能从那个例子中吸取教训。
有办法吗?
这是我的代码(不包括导入,因为 Eclipse 会自动建议):
public class Fpos extends JFrame
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
Fpos frame = new Fpos();
frame.setVisible(true);
frame.setLocationRelativeTo(null); //make frame center of screen
} catch (Exception e) {e.printStackTrace();}
}
});
}
public Fpos()
{
//create Jpanel
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(10, 10, 1300, 700);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
//create label TOTAL
JLabel lblTotal = new JLabel("TOTAL : Rp.");
lblTotal.setFont(new Font("Wide Latin", Font.PLAIN, 30));
lblTotal.setBounds(33, 25, 312, 31);
contentPane.add(lblTotal);
//create label Total Amount
JLabel lblNewLabel = new JLabel("123,456,789");
lblNewLabel.setHorizontalAlignment(SwingConstants.RIGHT);
lblNewLabel.setFont(new Font("Wide Latin", Font.PLAIN, 60));
lblNewLabel.setBounds(583, 19, 659, 61);
contentPane.add(lblNewLabel);
//create jtable in scrollpane
String[] columnNames = {"PLU", "NAME", "UOM", "QTY", "PRICE","AMOUNT"};
Object[][] data = {{"", "", "", "", "", ""}};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model);
table.setFont(new Font("Tahoma", Font.PLAIN, 20));
table.setRowHeight(25);
JScrollPane sp=new JScrollPane(table);
sp.setBounds(25,100,1240,556);
contentPane.add(sp);
//set column width
TableColumnModel columnModel = table.getColumnModel();
short a[] = {150,540,50,150,150,200};
for(byte i=0;i<6;i++) { columnModel.getColumn(i).setPreferredWidth(a[i]); }
//render column format left alignment
for(byte i=0;i<3;i++) {table.getColumnModel().getColumn(i).setCellRenderer(new TextTableCellRenderer());}
//render column format ###,##0 right alignment
for(byte i=3;i<6;i++) {table.getColumnModel().getColumn(i).setCellRenderer(new NumberTableCellRenderer());}
//make cursor blinking on selected cell + select all cell value
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
table.changeSelection(0, 0, false, false);
if (table.editCellAt(0, 0))
{
Component editor = table.getEditorComponent();
editor.setFont(new Font("Tahoma", Font.PLAIN, 20));
editor.requestFocusInWindow();
((JTextComponent)editor).selectAll(); //select all cell value
//key binding
Action pindah = new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
//add row at last row
model.addRow(data);
//i want to add new blank row but somehow there is value on column 0, so I have to set it blank. If you have a solution on this, you're very welcome
model.setValueAt("", model.getRowCount()-1, 0);
//make cursor blinking on selected cell + select all cell value
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
table.changeSelection(0, 0, false, false);
if (table.editCellAt(model.getRowCount()-1, 0))
{
Component editor = table.getEditorComponent();
editor.setFont(new Font("Tahoma", Font.PLAIN, 20));
editor.requestFocusInWindow();
((JTextComponent)editor).selectAll(); //select all cell value
}
}
});
}
};
((JComponent) editor).getInputMap().put(KeyStroke.getKeyStroke((char) KeyEvent.VK_ENTER), "pindah");
((JComponent) editor).getRootPane().getActionMap().put("pindah", pindah);
}
}
});
}
// render column format left alignment
public class TextTableCellRenderer extends DefaultTableCellRenderer
{public TextTableCellRenderer() {{setHorizontalAlignment(JLabel.LEFT);}} }
// render column format to ###,##0
public class NumberTableCellRenderer extends DefaultTableCellRenderer
{
public NumberTableCellRenderer() {setHorizontalAlignment(JLabel.RIGHT);}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (value instanceof Number) {value = NumberFormat.getNumberInstance().format(value);}
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
不是答案,而是对您的代码的一些评论。
首先您需要了解事件调度线程 (EDT)。需要在 EDT 上更新 GUI 组件。
通常您不需要继续嵌套 SwingUtilities.invokeLater() 代码,因为您确实在 EDT 上创建了 GUI。
我们需要添加 invokeLater(...)
来制作第一个单元格 editable 并让光标闪烁的原因是,如果框架不可见,您将无法在组件上设置焦点.因此 invokeLater(...)
允许我们将代码添加到 EDT 的末尾,以便它在 main() 方法中的 setVsible(...) 语句之后执行。
因此,如果您确实想使用键绑定,您可以在 Fpos 的构造函数中设置所有键绑定 class。
但是,我不知道当前要求的正确解决方案。
目前,ActionListener 添加到用作单元格编辑器的 JTextField。当您按下 Enter 键时,将调用侦听器并调用 table 的 stop cell editing logic
,这意味着将编辑器中的值添加到 TableModel 并从 [=33] 中删除单元格编辑器=].
因此您不能简单地向编辑器添加键绑定,因为您需要发生此默认行为。
我想您可以创建自定义单元格编辑器。然后在 ActionListener 中,您可以添加其他要求。