如何根据 TableView 中的行元素自定义 TableCell/TableColumn 内容 (JavaFX)
Howto customize TableCell/TableColumn content according to its row element in TableView (JavaFX)
问题
我有一个 TableColumn<User, String> colPassword
目前 仅 显示现有密码(字符串)作为每个条目(行)的屏蔽。
需要
我需要你的帮助,这样每个 TableCell
只显示 masked 密码: user.isManager == true,否则密码应该是unmasked.
我目前的做法
为了便于理解,我将只提供关键部分。
public class User implements Serializable {
private Long id;
private boolean deleted = false;
private final BooleanProperty manager = new SimpleBooleanProperty();
private final StringProperty password = new SimpleStringProperty("");
public User() {
}
public boolean isManager() {
return manager.get();
}
public void setManager(boolean value) {
manager.set(value);
}
public BooleanProperty managerProperty() {
return manager;
}
GUI 用户控制器
public class UsersController {
@FXML
private TableView<User> tblUsers;
@FXML
private TableColumn<User, String> colPassword;
private void initTableColumns() {
colPassword.setCellValueFactory(cellData
-> cellData.getValue().passwordProperty()
);
colPassword.setCellFactory((TableColumn<User, String> param) -> {
return new PasswordFieldCell();
});
}
这里是自定义的 TabelCell
public class PasswordFieldCell extends TableCell<User, String> {
private final Label lbl;
public PasswordFieldCell() {
lbl = new Label();
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.setGraphic(null);
}
private String generatePasswordString(int len) {
String dots = "";
for (int i = 0; i < len; i++) {
dots += "*";
}
return dots;
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
lbl.setText(generatePasswordString(item.length()));
setGraphic(lbl);
} else {
setGraphic(null);
}
}
}
解决方案
在 VGR 的帮助下,我在 PasswordFieldCell 中找到了这个解决方案。
public class PasswordFieldCell extends TableCell<User, String> {
private final Label lbl;
public PasswordFieldCell() {
lbl = new Label();
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.setGraphic(null);
}
private String generatePasswordString(int len) {
String dots = "";
for (int i = 0; i < len; i++) {
dots += "*";
}
return dots;
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
int row = getIndex();
User user = getTableView().getItems().get(row);
if (user.isManager()) { // mask password
lbl.setText(generatePasswordString(item.length()));
} else { // unmask password
lbl.setText(item);
}
setGraphic(lbl);
} else {
setGraphic(null);
}
}
}
您的 PasswordFieldCell class 从 TableCell.
继承了很多有用的方法
特别是,您继承了一个 getTableView() 方法和一个 returns 当前单元格行的 getIndex() 方法。这些就是您在 updateItem
方法中查找单元格行值所需的全部内容:
int row = getIndex();
User user = getTableView().getItems().get(row);
问题
我有一个 TableColumn<User, String> colPassword
目前 仅 显示现有密码(字符串)作为每个条目(行)的屏蔽。
需要
我需要你的帮助,这样每个 TableCell
只显示 masked 密码: user.isManager == true,否则密码应该是unmasked.
我目前的做法
为了便于理解,我将只提供关键部分。
public class User implements Serializable {
private Long id;
private boolean deleted = false;
private final BooleanProperty manager = new SimpleBooleanProperty();
private final StringProperty password = new SimpleStringProperty("");
public User() {
}
public boolean isManager() {
return manager.get();
}
public void setManager(boolean value) {
manager.set(value);
}
public BooleanProperty managerProperty() {
return manager;
}
GUI 用户控制器
public class UsersController {
@FXML
private TableView<User> tblUsers;
@FXML
private TableColumn<User, String> colPassword;
private void initTableColumns() {
colPassword.setCellValueFactory(cellData
-> cellData.getValue().passwordProperty()
);
colPassword.setCellFactory((TableColumn<User, String> param) -> {
return new PasswordFieldCell();
});
}
这里是自定义的 TabelCell
public class PasswordFieldCell extends TableCell<User, String> {
private final Label lbl;
public PasswordFieldCell() {
lbl = new Label();
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.setGraphic(null);
}
private String generatePasswordString(int len) {
String dots = "";
for (int i = 0; i < len; i++) {
dots += "*";
}
return dots;
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
lbl.setText(generatePasswordString(item.length()));
setGraphic(lbl);
} else {
setGraphic(null);
}
}
}
解决方案
在 VGR 的帮助下,我在 PasswordFieldCell 中找到了这个解决方案。
public class PasswordFieldCell extends TableCell<User, String> {
private final Label lbl;
public PasswordFieldCell() {
lbl = new Label();
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.setGraphic(null);
}
private String generatePasswordString(int len) {
String dots = "";
for (int i = 0; i < len; i++) {
dots += "*";
}
return dots;
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
int row = getIndex();
User user = getTableView().getItems().get(row);
if (user.isManager()) { // mask password
lbl.setText(generatePasswordString(item.length()));
} else { // unmask password
lbl.setText(item);
}
setGraphic(lbl);
} else {
setGraphic(null);
}
}
}
您的 PasswordFieldCell class 从 TableCell.
继承了很多有用的方法特别是,您继承了一个 getTableView() 方法和一个 returns 当前单元格行的 getIndex() 方法。这些就是您在 updateItem
方法中查找单元格行值所需的全部内容:
int row = getIndex();
User user = getTableView().getItems().get(row);