Reputation: 43
I found keybinding topic (JTable Key Bindings) similar to this. I learned that its keybinding is bound to the table not the editor.
My goal is any input on editor ending with VK-ENTER, it executes action pindah (which is adding new row and set cursor blinking on new row). I'm sorry, I failed to learn from that example.
Is there a way for that?
Here is my code (excluding the import as Eclipse will suggest it automatically):
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);
}
}
}
Upvotes: 0
Views: 300
Reputation: 324108
Not an answer but several comments about your code.
First you need to understand about the Event Dispatch Thread (EDT). Updates to GUI components need to be done on the EDT.
Normally you don't need to keep nesting SwingUtilities.invokeLater() code since you do create your GUI on the EDT.
The reason we needed to add the invokeLater(...)
to make the first cell editable and have the cursor blinking is that you can't set focus on a component if the frame is not visible. So the invokeLater(...)
allows us to add code to the end of the EDT so it executed after the setVsible(...) statement in your main() method.
So, if you do want to use Key Bindings you could just set all the Key Bindings in the constructor of your Fpos class.
However, I don't know the proper solution for this current requirement.
Currently, an ActionListener is added to the JTextField that is used as the cell editor. When you press the Enter key the listener is invoked and the stop cell editing logic
of the table is invoked, which means the value in the editor is added to the TableModel and the cell editor is removed from the table.
So you can't just simply add a Key Binding to the editor since you need this default behaviour to occur.
I guess you could create a custom cell editor. Then in the ActionListener you can add your additional requirements.
Upvotes: 2