问题描述
我们在用Javafx开发应用程序的时候,TableView是比较常用的用来展示数据的控件,但是它的灵活性确实没有WEB开发里面的控件好,比如,我遇到的问题就有:
数据库存储里面的ID列(序号)一般是自增性质的,不停的增加、删除操作后,这个序号列就会乱,数字 不连续,而我们要显示到GUI里面的序号列肯定需要按正常顺序显示的,本文提供构造顺序序号列的方法;
操作列(比如删除)的渲染问题,一种思路就是在表格控件之外加一个删除按钮,点击按钮的时候判断一下当前选中的行,然后执行删除操作。本文讨论另外一种思路,单独在表格里面添加一个删除列(每行都有一个删除按钮,单击则删除所在行数据);
很多时候,我们具有个性化显示表格数据的需求,比如,显示学生数学成绩的某列,我们希望把那些低于60分的分数标红,而及格分数则不做处理;
TableView理解
JavaFX表格控件渲染数据主要有两种方法:
1. setCellValueFactory(new PropertyValueFactory<>(“字段名”)),适合表格列数已知,有对应实体的情况(比如,学生信息,我们假定它只有姓名、性别、学号、地址、联系方式等固定字段,则适合采用此种方式进行渲染);
2. setCellValueFactory(new MapValueFactory<>(“对应列的键值”)),适合表格列数在渲染之前未知,需要根据传入数据的维数确定的情况,此时因为没有固定列数,所以一般数据也没有对应的实体类,数据需要用Map进行构造,一行数据就是一个Map;
本文主要针对列数已知的情况,Map的情况同理。
代码DEMO
工程目录如下图:
Main.java
/**
* 实现表格的序号列的计算填充,
* 实现按钮操作列的正常显示以及事件绑定
*/
package application;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(this.getClass().getResource("FXTable.fxml"));
// 为表格设置控制器
loader.setController(new TableController());
AnchorPane rootPane = loader.load();
Scene scene = new Scene(rootPane,506,460);
primaryStage.sizeToScene();
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Student.java
package application;
public class Student {
private String firstName;
private String lastName;
private int age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}
TableController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.ImageView;
public class TableController implements Initializable {
@FXML
private Label fxLabel;
@FXML
private TableView<Student> stuTable;
@FXML
private TableColumn<Student, String> idCol, fNameCol, lNameCol, delCol;
@FXML
private TableColumn<Student, Integer> ageCol;
@FXML
private TableColumn<Student, Boolean> isAdultCol;
public ObservableList<Student> getStuData() {
Student stu1 = new Student("赵", "哈", 16);
Student stu2 = new Student("钱", "大", 26);
Student stu3 = new Student("孙", "阿", 23);
Student stu4 = new Student("李", "佛山", 17);
Student stu5 = new Student("周", "阿萨德", 23);
Student stu6 = new Student("吴", "更好", 12);
Student stu7 = new Student("郑", "和", 28);
Student stu8 = new Student("王", "费", 23);
Student stu9 = new Student("刘", "的", 15);
Student stu10 = new Student("关", "时是", 23);
Student stu11 = new Student("张", "良好", 19);
Student stu12 = new Student("诸葛", "列", 23);
Student stu13 = new Student("司马", "咯跑", 20);
ObservableList<Student> stuLists = FXCollections.observableArrayList(stu1, stu2, stu3, stu4, stu5, stu6, stu7,
stu8, stu9, stu10, stu11, stu12, stu13);
return stuLists;
}
/**
* 显示学生表格
*
* @param stuLists
*/
public void showStuTable(ObservableList<Student> stuLists) {
fNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
lNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
// ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));
idCol.setCellFactory((col) -> {
TableCell<Student, String> cell = new TableCell<Student, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
int rowIndex = this.getIndex() + 1;
this.setText(String.valueOf(rowIndex));
}
}
};
return cell;
});
ageCol.setCellFactory((col) -> {
TableCell<Student, Integer> cell = new TableCell<Student, Integer>() {
@Override
public void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
int age = this.getTableView().getItems().get(this.getIndex()).getAge();
this.setText(String.valueOf(age));
if (age < 18) {
this.getStyleClass().add("mark");
}
}
}
};
return cell;
});
isAdultCol.setCellFactory((col) -> {
TableCell<Student, Boolean> cell = new TableCell<Student, Boolean>() {
@Override
public void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
CheckBox checkBox = new CheckBox();
this.setGraphic(checkBox);
checkBox.selectedProperty().addListener((obVal, oldVal, newVal) -> {
if (newVal) {
// 添加选中时执行的代码
System.out.println("第" + this.getIndex() + "行被选中!");
// 获取当前单元格的对象
// this.getItem();
}
});
}
}
};
return cell;
});
delCol.setCellFactory((col) -> {
TableCell<Student, String> cell = new TableCell<Student, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
ImageView delICON = new ImageView(getClass().getResource("delete.png").toString());
Button delBtn = new Button("删除", delICON);
this.setGraphic(delBtn);
delBtn.setOnMouseClicked((me) -> {
Student clickedStu = this.getTableView().getItems().get(this.getIndex());
System.out.println("删除 " + clickedStu.getFirstName() + clickedStu.getLastName() + " 的记录");
});
}
}
};
return cell;
});
stuTable.setItems(stuLists);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
fxLabel.setWrapText(true);
fxLabel.setText(" javafx_Label标签的换行测试,用于弹出框的提示信息测试,Label控件也可以换行。");
this.showStuTable(this.getStuData());
}
}
FXTable.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="461.0" prefWidth="489.0" stylesheets="@Fxtable.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TableView fx:id="stuTable" layoutY="54.0" prefHeight="407.0" prefWidth="402.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="54.0">
<columns>
<TableColumn fx:id="idCol" prefWidth="75.0" text="序号" />
<TableColumn fx:id="fNameCol" prefWidth="87.0" text="姓氏" />
<TableColumn fx:id="lNameCol" prefWidth="79.0" text="名字" />
<TableColumn fx:id="ageCol" prefWidth="73.0" text="年龄" />
<TableColumn fx:id="delCol" prefWidth="86.0" text="删除列" />
<TableColumn fx:id="isAdultCol" prefWidth="88.0" text="成年?" />
</columns>
</TableView>
<Label fx:id="fxLabel" layoutY="-1.0" prefHeight="56.0" prefWidth="402.0" />
</children>
</AnchorPane>
运行截图:
实现描述:
实体类里面无ID字段,表格做数据展示的时候临时构造顺序ID列数据;
删除操作列的渲染,并且添加单击事件,能够实时响应删除动作;
年龄一列的个性化显示,未成年年龄显示为红色字体;
另,DEMO源码可以向原版作者要,以下链接是原文出处。
---------------------
作者:M-Chung
来源:CSDN
原文:https://blog.csdn.net/mrchung2016/article/details/71774496
版权声明:本文为博主原创文章,转载请附上博文链接!