JTable 失去焦点时取消编辑状态
reference: http://tips4java.wordpress.com/2008/12/12/table-stop-editing/
当JTable的单元格处于编辑状态时,如果用户触发以下事件,表格就会退出编辑状态,进而调用TableModel的
public void setValueAt(Object aValue, int row, int column)
1. 回车确认
2. 使用方向键或tab移动到别的单元格
3. 鼠标点击别的单元格
但是,如果用户点击了表格之外的控件,表格中单元格还是处于编辑状态,此时如果点击的是“保存”按钮,由于单元格并没有接受用户的输入,导致当前编辑的单元格的值为null,用户输入的数据没有保存。
同时,由于表格中的所有单元格是共用一个CellEditor,当用户新建一行时,通常会让光标移动到新建的行的某一个单元格,此时原来正在编辑的单元格就会替换到新增加的行中,而之前单元格的输入的内容没有保存。
因此,在触发其他操作之前,最好能够取消表格正在编辑的状态。
方法1.
JTable table = new JTable(...);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
当其他控件获取焦点后,表格会停止编辑,但是点击最小化时没有效果。
方法2.
if (table.isEditing())
table.getCellEditor().stopCellEditing();
在需要取消表格编辑状态的按钮等控件的事件响应中根据具体情况来取消表格的编辑状态。
原文说点击表格的表头,使用第一种方法,表格不会退出编辑状态,但是经测试也是会退出编辑状态的。
表格Model简单继承DefaultTableModel
package com.aquar.table; import com.aquar.data.Movie; import javax.swing.table.DefaultTableModel; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Vector; /** * Created with IntelliJ IDEA. * User: Edison * Date: 13-8-16 * Time: 下午10:46 * A table model for movies. */ public class TableModelMovie extends DefaultTableModel { private static final int COL_NAME = 0; private static final int COL_PREMIERE = COL_NAME + 1; private static final int COL_DIRCTOR = COL_PREMIERE + 1; public TableModelMovie() { init(); mockData(); } private void init() { columnIdentifiers.add("Name"); columnIdentifiers.add("Premiere"); columnIdentifiers.add("Director"); } /** * make some movies. */ private void mockData() { List<Movie> list = new ArrayList<>(); list.add(new Movie("The Shawshank Redemption", new Date(), "Frank Darabont")); list.add(new Movie("The Godfather", new Date(), " Francis Ford Coppola")); list.add(new Movie("Pulp Fiction", new Date(), "Quentin Tarantino")); list.add(new Movie("The Dark Knight", new Date(), "Frank Darabont")); fillTableData(list); } private void fillTableData(List<Movie> movies) { dataVector.clear(); for (Movie movie : movies) { Vector rowVector = new Vector(); rowVector.add(movie); dataVector.add(rowVector); } fireTableDataChanged(); } @Override public Object getValueAt(int row, int column) { Object ret = ""; if (row > dataVector.size()) { return ret; } // Get one row data. Vector rowData = (Vector) dataVector.elementAt(row); Movie movie = (Movie) rowData.elementAt(0); switch (column) { case COL_NAME: ret = movie.getName(); break; case COL_PREMIERE: ret = movie.getPremiere().toString(); break; case COL_DIRCTOR: ret = movie.getDirector(); break; default: break; } return ret; } @Override public void setValueAt(Object aValue, int row, int column) { if (row > dataVector.size()) { return ; } // Get one row data. Vector rowData = (Vector) dataVector.elementAt(row); Movie movie = (Movie) rowData.elementAt(0); switch (column) { case COL_NAME: movie.setName(aValue.toString()); break; case COL_DIRCTOR: movie.setDirector(aValue.toString()); break; default: break; } } @Override public boolean isCellEditable(int row, int column) { return column == COL_NAME || column == COL_DIRCTOR; } }
数据对象
package com.aquar.data; import java.util.Date; import java.util.List; /** * Created with IntelliJ IDEA. * User: Edison * Date: 13-8-16 * Time: 下午10:30 * To change this template use File | Settings | File Templates. */ public class Movie { private String name; private Date premiere; private String publisher; private String director; private List<String> starrings; public Movie(String movName, Date movPremiere, String movDirector) { this.name = movName; this.premiere = movPremiere; this.director = movDirector; } public String getName() { return name; } public Date getPremiere() { return premiere; } public String getPublisher() { return publisher; } public String getDirector() { return director; } public List<String> getStarrings() { return starrings; } public void setName(String name) { this.name = name; } public void setPremiere(Date premiere) { this.premiere = premiere; } public void setPublisher(String publisher) { this.publisher = publisher; } public void setDirector(String director) { this.director = director; } public void setStarrings(List<String> starrings) { this.starrings = starrings; } }
程序入口和UI
package com.aquar.main; import com.aquar.table.TableModelMovie; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * Created with IntelliJ IDEA. * User: Edison * Date: 13-7-14 * Time: 下午11:55 * To change this template use File | Settings | File Templates. */ public class MainFrame { private final int width = 800; private final int height = 600; private JFrame mFrame; private JTable movTable; public MainFrame() { mFrame = new JFrame(); mFrame.setLayout(new BorderLayout(0, 0)); mFrame.setSize(new Dimension(width, height)); mFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); initUI(); mFrame.setVisible(true); } private void initUI() { TableModelMovie modelMovie = new TableModelMovie(); movTable = new JTable(modelMovie); movTable.setRowHeight(20); movTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); JScrollPane scrollPane = new JScrollPane(movTable); mFrame.add(scrollPane, BorderLayout.CENTER); JPanel footPanel = new JPanel(); JButton newBtn = new JButton("New"); newBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // if (movTable.isEditing()) { // movTable.getCellEditor().stopCellEditing(); // } } }); footPanel.add(newBtn); mFrame.add(footPanel, BorderLayout.SOUTH); } public void show() { } public static void main(String[] args) { new MainFrame(); } }