最近在着手一个学生管理系统的编写,涉及到TableView的使用,这前前后后的也有了些经验和想法想要记录和分享一下(事实上我正在想要用html网页代替界面),更多的是学习之用。
在IDEA中,按住Ctrl然后点中TableView关键字会自动跟进到它定义的地方,我们可以先看看这里面到底都有些什么东西。
你会比较先的看到它的两个构造函数:
// 第一个构造函数
public TableView() {
this(FXCollections.<S>observableArrayList());
}
// 第二个构造函数
public TableView(ObservableList<S> items) {
getStyleClass().setAll(DEFAULT_STYLE_CLASS);
setAccessibleRole(AccessibleRole.TABLE_VIEW);
// we quite happily accept items to be null here
setItems(items);
// install default selection and focus models
// it's unlikely this will be changed by many users.
setSelectionModel(new TableViewArrayListSelectionModel<S>(this));
setFocusModel(new TableViewFocusModel<S>(this));
// we watch the columns list, such that when it changes we can update
// the leaf columns and visible leaf columns lists (which are read-only).
getColumns().addListener(weakColumnsObserver);
// watch for changes to the sort order list - and when it changes run
// the sort method.
getSortOrder().addListener((ListChangeListener<TableColumn<S, ?>>) c -> {
doSort(TableUtil.SortEventType.SORT_ORDER_CHANGE, c);
});
// We're watching for changes to the content width such
// that the resize policy can be run if necessary. This comes from
// TreeViewSkin.
getProperties().addListener(new MapChangeListener<Object, Object>() {
@Override
public void onChanged(Change<? extends Object, ? extends Object> c) {
if (c.wasAdded() && SET_CONTENT_WIDTH.equals(c.getKey())) {
if (c.getValueAdded() instanceof Number) {
setContentWidth((Double) c.getValueAdded());
}
getProperties().remove(SET_CONTENT_WIDTH);
}
}
});
isInited = true;
}
可以大致的看一下,不过最重要的是清楚了一点:TableView内部是维护了一个类型为FXCollections.< S >observableArrayList的集合。其中< S >代表用户自己定义的类型。
也可以看到如何给Table添加监听者:
getProperties().addListener(new MapChangeListener<Object, Object>() {
@Override
public void onChanged(Change<? extends Object, ? extends Object> c) {
if (c.wasAdded() && SET_CONTENT_WIDTH.equals(c.getKey())) {
if (c.getValueAdded() instanceof Number) {
setContentWidth((Double) c.getValueAdded());
}
getProperties().remove(SET_CONTENT_WIDTH);
}
}
});
总之你会看到许多非常有意思的东西,这里就不细说了,有兴趣的可以去自己读一下,对于理解TableView控件有着非常好的帮助,你能顾更加理解它运行的原理还有机制。
我们就来看看实际的运用吧,官方给出了非常详细的文档,有幸找到了把它翻译成较好版本中文的网站,直接给链接,里面就有一些简单的应用:
简单的应用:http://www.javafxchina.net/blog/2015/04/doc03_tableview/
官方的文档:http://docs.oracle.com/javafx/2/ui_controls/table-view.htm
一种是维护类的TableColumn<Person,String>类型,列的每一个数据都是一个类(这里是一个Person类),而String类型对应列名。映射需要这样设置:
col.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName")); // firstName对应列名
另一种是维护Map的TableColumn<Map,String>类型,列的每一个数据都是Map。设置映射时需要这样:
col.setCellValueFactory(new MapValueFactory(colName)); // colName对应字符类型列名```
可以向官方文档中那样,也可以先增加一个TextFieldTableCell,然后再添加响应函数:
// 设置CellFactory,填充一个TextField进列
col.setCellFactory(TextFieldTableCell.<Map>forTableColumn());
// 设置编辑响应的函数
col.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Map, String>>() {
@Override public void handle(TableColumn.CellEditEvent<Map, String> t) {
System.out.println("检测到改变");
// 这里修改维护的对应的设置进TableView的ObservableList集合
}
});
添加行删除行也是同样的操作,可以直接修改TableView维护的集合来完成。
这就不仅仅要删除集合中的数据,还要从表格里面的Columns集合中删除相应的数据才可以,或许你还会在删除和增加中加入一定的判断来保证操作的正确性:
table.getColumns().add(tempCol); // 列表中显示新增的列
table.getColumns().remove(index); // 删除index位置的列
你大可以选择向源文件中的那样,通过getProperties().addListener来完成监听,同样也可以添加进一个ListChangeListener:
// 给table设置监听器监听列的变化
table.getColumns().addListener(new ListChangeListener() {
@Override
public void onChanged(Change c) {
c.next(); // 接受变化,否则报错
// 处理列拖动后的事件
if (c.wasRemoved()) {
// 定义一个保存了现在列排序的集合
List<TableColumn<ObservableList<Map>, String>> newList =
new ArrayList<>(table.getColumns());
// 定义一个保存了原来列排序的集合
List<TableColumn<ObservableList<Map>, String>> oldList =
new ArrayList<>(c.getList());
// 相关操作
} // end if:拖动事件处理完毕
}
});
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
table.setItems(ObservableList)
RoomIdCol.setCellValueFactory(new PropertyValueFactory<Person, String>("RoomIdCol"))
firstNameCol.setCellValueFactory
(new Callback<TableColumn.CellDataFeatures<Person, String>,
ObservableValue<String>>() {
@Override
public ObservableValue<String> call(CellDataFeatures<Person, String> arg0) {
// return new
// SimpleStringProperty(arg0.getValue(),"sd",arg0.getValue().getFirstName());
// //bean, bean的名称,值
return new SimpleStringProperty(arg0.getValue().getFirstName());
// 这样你可以不建立值与对象的映射关系。
}
});
SimpleStringProperty(arg0.getValue(),"sd",arg0.getValue().getFirstName());
firstNameCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
@Override
public TableCell<Person, String> call( // 单元格内容
TableColumn<Person, String> arg0) {
return new TableCell<Person, String>() { @Override
protected void updateItem(final String str,boolean arg1) {
super.updateItem(str, arg1);
if (arg1) { setText(null);
setGraphic(null);
else { setText(str);
setGraphic(new CheckBox());
}
}
}
});
lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
//TableColumn设置sort的3个方法
firstNameCol.setSortNode(new Text("a")); // 默认是表头上的小图标三角形,可以改变
firstNameCol.setSortable(true); // 设置可排序
firstNameCol.setSortType(SortType.DESCENDING);//设置升降序
firstNameColumn = new TableColumn<Person, String>("First");
firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
// firstNameColumn.setCellFactory(TextFieldCellFactory.<Person>forTableColumn());
lastNameColumn = new TableColumn<Person, String>("Last");
lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
// lastNameColumn.setCellFactory(TextFieldCellFactory.<Person>forTableColumn());
nameColumn = new TableColumn<Person, String>("Name");
nameColumn.getColumns().setAll(firstNameColumn, lastNameColumn);
.table-view .table-row-cell {
-fx-background-insets: 0;
}
.table-row-cell:empty .table-cell {
-fx-border-width: 0px;
}
tableView.setRowFactory(new Callback<TableView<T>, TableRow<T>>() {
@Override
public TableRow<T> call(TableView<T> param) {
return new TableRowControl();
}
});
class TableRowControl extends TableRow<T> {
public TableRowControl() {
super();
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.getButton().equals(MouseButton.PRIMARY)
&& event.getClickCount() == 2
&& TableRowControl.this.getIndex() < tableView.getItems().size()) {
//doSomething
}
}
});
}
}
tableView.getItems().add(selectedRow, newRecord);
@Override
public void startEdit() {
if (!this.getTableRow().isVisible()) {
return;
}
super.startEdit();
if (checkBox == null) {
createCheckBox();
}
setText(null);
setGraphic(checkBox);
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(getItem().toString());
setGraphic(null);
}
table.getSelectionModel().getSelectedCells().get(0).getTableColumn()
table.setTableMenuButtonVisible(true);
ListChangeListener<Person> indicesListener = new ListChangeListener<Person>() {
@Override public void onChanged(Change<? extends Person> c) {
while (c.next()) {
selectionUpdated(c.getAddedSubList(), c.getRemoved());
}
}
};
tableView.getSelectionModel().getSelectedItems().addListener(indicesListener);
tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
getSelectedIndex()
getSelectedItem()
selectedIndexProperty()
selectedItemProperty()
select(int index)
select(T obj)
selectFirst()
selectLast()
...
clearSelection()
clearSelection(int index)
setSelectionMode(SelectionMode.MULTIPLE);
selectIndices(int index, int... indices)
selectRange(int start, int end)
select(int row, TableColumn<S,?> column)
selectAboveCell()
selectBelowCell()
selectLeftCell()
selectRightCell()
setCellSelectionEnabled(boolean value)