JavaFX 表格单元格编辑
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24732883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaFX Table Cell Editing
提问by Adam.J
I am trying to make a program in Java to manage my bookie accounts. I'm new to java, so I thought I would chose something simple to see how things work. I decided to use a tableview and make the individual cells editable. I've been following this tutorial http://java-buddy.blogspot.co.uk/2012/04/javafx-2-editable-tableview.html. It details how to do it using java code, and copying that into a new class works perfectly. I decided to try and tweak it to work with FXML, since I like Sceneviewer. My issue is, data is loaded in to the table, but when I click/doubleclick a cell, nothing happens. Here's my code.
我正在尝试用 Java 制作一个程序来管理我的博彩账户。我是 Java 新手,所以我想我会选择一些简单的东西来看看事情是如何工作的。我决定使用 tableview 并使单个单元格可编辑。我一直在关注本教程http://java-buddy.blogspot.co.uk/2012/04/javafx-2-editable-tableview.html。它详细说明了如何使用 java 代码来完成它,并将其复制到一个新类中可以完美地工作。我决定尝试调整它以使用 FXML,因为我喜欢 Sceneviewer。我的问题是,数据已加载到表格中,但是当我单击/双击单元格时,没有任何反应。这是我的代码。
testController.java
测试控制器.java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.util.Callback;
import java.net.URL;
import java.util.ResourceBundle;
public class testController implements Initializable {
@FXML
private TableColumn<Account, String> usernameCol;
@FXML
private TableColumn<Account, String> balanceCol;
@FXML
private TableView<Account> accountTable;
@FXML
private TableColumn<Account, String> bookieCol;
@FXML
private TableColumn<Account, String> passwordCol;
private ObservableList<Account> dataList =
FXCollections.observableArrayList(
new Account("bookie", "username", "password", "0"));
@Override
public void initialize(URL location, ResourceBundle resources) {
Callback<TableColumn, TableCell> cellFactory =
new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
return new EditingCell();
}
};
bookieCol.setCellValueFactory(
new PropertyValueFactory<>("fieldBookie"));
usernameCol.setCellValueFactory(
new PropertyValueFactory<>("fieldUsername"));
usernameCol.setOnEditCommit(
new EventHandler<TableColumn.CellEditEvent<Account, String>>() {
@Override public void handle(TableColumn.CellEditEvent<Account, String> t) {
((Account)t.getTableView().getItems().get(
t.getTablePosition().getRow())).setFieldUsername(t.getNewValue());
}
});
passwordCol.setCellValueFactory(
new PropertyValueFactory<Account, String>("fieldPassword"));
balanceCol.setCellValueFactory(
new PropertyValueFactory<Account, String>("fieldBalance"));
accountTable.setItems(dataList);
}
class EditingCell extends TableCell<Account, String> {
private TextField textField;
public EditingCell() {
}
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
textField.selectAll();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(String.valueOf(getItem()));
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(textField);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.setOnKeyPressed(t -> {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
}
}
And here is my Account.java file.
这是我的 Account.java 文件。
import javafx.beans.property.SimpleStringProperty;
public class Account {
private SimpleStringProperty fieldBookie;
private SimpleStringProperty fieldUsername;
private SimpleStringProperty fieldPassword;
private SimpleStringProperty fieldBalance;
Account(String fbookie, String fusername, String fpassword, String fbalance){
this.fieldBookie = new SimpleStringProperty(fbookie);
this.fieldUsername = new SimpleStringProperty(fusername);
this.fieldPassword = new SimpleStringProperty(fpassword);
this.fieldBalance = new SimpleStringProperty(fbalance);
}
public String getFieldBookie() {
return fieldBookie.get();
}
public String getFieldUsername() {
return fieldUsername.get();
}
public String getFieldPassword() {
return fieldPassword.get();
}
public String getFieldBalance() {
return fieldBalance.get();
}
public void setFieldBookie(String fBookie) {
fieldBookie.set(fBookie);
}
public void setFieldUsername(String fUsername) {
fieldUsername.set(fUsername);
}
public void setFieldPassword(String fPassword) {
fieldUsername.set(fPassword);
}
public void setFieldBalance(String fBalance) {
fieldUsername.set(fBalance);
}
}
Lastly, here is my fxml file.
最后,这是我的 fxml 文件。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.canvas.*?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<Group xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="testController">
<children>
<TableView fx:id="accountTable" editable="true" prefHeight="291.0" prefWidth="302.0">
<columns>
<TableColumn fx:id="bookieCol" prefWidth="75.0" text="Bookie" />
<TableColumn fx:id="usernameCol" prefWidth="75.0" text="Username" />
<TableColumn fx:id="passwordCol" prefWidth="75.0" text="Password" />
<TableColumn fx:id="balanceCol" prefWidth="75.0" text="Balance" />
</columns>
</TableView>
</children>
</Group>
As I said earlier, nothing happens when I click on the Username cell. No errors, no textfield, just nothing. Any help would be greatly appreciated! Thanks
正如我之前所说,当我单击用户名单元格时没有任何反应。没有错误,没有文本字段,什么都没有。任何帮助将不胜感激!谢谢
采纳答案by crusam
I haven`t tried your example, but I think you just forgot to set the cellFactory for the specific column. Adding the folowing line should fix it:
我没有试过你的例子,但我认为你只是忘记为特定列设置 cellFactory 。添加以下行应该修复它:
usernameCol.setCellFactory(cellFactory);
回答by milosz
You can add the textField to editing cell using :TextFieldTableCell.forTableColumn();
If you need comboBox try :ComboBoxTableCell.forTableColumn(list);
您可以使用以下方法将 textField 添加到编辑单元格:TextFieldTableCell.forTableColumn();
如果您需要组合框,请尝试:ComboBoxTableCell.forTableColumn(list);
// TextField
usernameCol.setCellFactory(TextFieldTableCell.forTableColumn());
//ComboBox
ObservableList<String> list =
FXCollections.observableArrayList();
list.add("name 1");
list.add("name 2");
list.add("name 3");
list.add("name 4");
Callback<TableColumn<Account, String>, TableCell<Account, String>> cbtc =
ComboBoxTableCell.forTableColumn(list);
usernameCol.setCellFactory(cbtc);
usernameCol.setCellFactory(cbtc);
回答by UniqUnicorn
I case someone needs a working example, I was able to get the code to work with this tutorialby adding a
如果有人需要一个工作示例,我可以通过添加一个代码来使代码与本教程一起使用
usernameCol.setCellFactory(
TextFieldTableCell.forTableColumn());
and changing the usernameCol.setOnEditCommit
to
并更改usernameCol.setOnEditCommit
为
usernameCol.setOnEditCommit(
(TableColumn.CellEditEvent<Account, String> t) ->
( t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setFieldUsername(t.getNewValue())
);
Here is the complete testController
class that should be working (Other files stayed the same)
这是testController
应该工作的完整类(其他文件保持不变)
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import java.net.URL;
import java.util.ResourceBundle;
public class testController implements Initializable {
@FXML
private TableColumn<Account, String> usernameCol;
@FXML
private TableColumn<Account, String> balanceCol;
@FXML
private TableView<Account> accountTable;
@FXML
private TableColumn<Account, String> bookieCol;
@FXML
private TableColumn<Account, String> passwordCol;
private ObservableList<Account> dataList =
FXCollections.observableArrayList(
new Account("bookie", "username", "password", "0"));
@Override
public void initialize(URL location, ResourceBundle resources) {
bookieCol.setCellValueFactory(
new PropertyValueFactory<>("fieldBookie"));
usernameCol.setCellValueFactory(
new PropertyValueFactory<>("fieldUsername"));
usernameCol.setCellFactory(
TextFieldTableCell.forTableColumn());
usernameCol.setOnEditCommit(
(TableColumn.CellEditEvent<Account, String> t) ->
( t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setFieldUsername(t.getNewValue())
);
passwordCol.setCellValueFactory(
new PropertyValueFactory<Account, String>("fieldPassword"));
balanceCol.setCellValueFactory(
new PropertyValueFactory<Account, String>("fieldBalance"));
accountTable.setItems(dataList);
}
}