JavaFXTableView-添加一行
我有一个应用程序,其中有一个tableview 我从数据库中获取信息并显示数据 有没有一种方法可以让tableview中的底行作为输入新数据的方式 我在网上看到了texfields和add按钮,但我想知道是否可以直接从tableview输入新数据JavaFXTableView-添加一行,javafx,tableview,Javafx,Tableview,我有一个应用程序,其中有一个tableview 我从数据库中获取信息并显示数据 有没有一种方法可以让tableview中的底行作为输入新数据的方式 我在网上看到了texfields和add按钮,但我想知道是否可以直接从tableview输入新数据 感谢您提供的任何帮助或建议您可以通过在自己的自定义类中扩展TableCell来提供此行为。然后,将其CellFactory中的列设置为这种类型的单元格,并在其中提供自定义实现。然后,您可以添加自己的实现,即当有人单击单元格时,如何在单元格中显示文本字段
感谢您提供的任何帮助或建议您可以通过在自己的自定义类中扩展TableCell来提供此行为。然后,将其CellFactory中的列设置为这种类型的单元格,并在其中提供自定义实现。然后,您可以添加自己的实现,即当有人单击单元格时,如何在单元格中显示文本字段。最后,您需要向tableview添加一个空行 我有一些TreeTableCell的示例代码,它很像TableCell。 您可以以此为例编写自己的自定义TableCell 自定义单元格 包be.vincentnagy.ehka.treetableview.cell
import be.vincentnagy.ehka.activity.Activity;
import be.vincentnagy.ehka.category.Category;
import be.vincentnagy.ehka.treetableview.item.CustomTreeItem;
import be.vincentnagy.ehka.treetableview.item.TotalTreeItem;
import javafx.geometry.Pos;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.input.KeyCode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.time.Month;
import java.time.Year;
/**
* @author Vincent Nagy
* A MoneyFormatCell is a custom implementation of a TreeTableCell.
* It provides editing functionality for specific cells
* and propagates changes to the underlying data items.
*/
public class MoneyFormatCell extends TreeTableCell<CustomTreeItem,Number>{
private TextField textField;
private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance();
private static final NumberFormat CURRENCY_FORMAT = NumberFormat.getCurrencyInstance();
static {
NUMBER_FORMAT.setMaximumFractionDigits(2);
NUMBER_FORMAT.setMinimumFractionDigits(2);
}
public MoneyFormatCell() {
}
/**
* updateItem gets called whenever a MoneyFormatCell changes state.
* Editing gets disabled for TotalTreeItem and CategoryTreeItem.
* Provides the TextBox inside the cell for input.
* @param item Item being added to the MoneyFormatCell. Only gets called at initial filling of the Table
* @param empty Whether or not the cell is empty
*/
@Override
protected void updateItem(Number item, boolean empty) {
super.updateItem(item, empty);
setAlignment(Pos.CENTER_RIGHT);
TreeItem<CustomTreeItem> treeItem = getTreeTableRow().getTreeItem();
//Set editable if it's a leaf(aka if it's an ActivityDataItem
setEditable(treeItem != null && treeItem.isLeaf());
//Set editable if it's not the the Totals row and not a Category row
setEditable(!(treeItem != null && (treeItem.getValue() instanceof TotalTreeItem || treeItem.getValue() instanceof Category)));
if(empty){
setText(null);
setGraphic(null);
}else {
if( isEditing()){
if(textField != null){
textField.setText(getString());
setText(null);
setGraphic(textField);
}
} else {
if(item == null){
if(textField != null && !textField.getText().equals("")){
stoppedEditing();
}
setText("");
}else{
setText(NumberFormat.getCurrencyInstance().format(item.doubleValue()));
}
setGraphic(null);
}
}
}
/**
* startEdit gets called whenever a MoneyFormatCell moves into editing mode.
* It creates the TextField element if it isn't already created
* and switches the graphics from string to the TextField.
*/
@Override
public void startEdit() {
if(isEditable()) {
super.startEdit();
if (textField == null) {
createTextField();
}
setText(null);
setGraphic(textField);
textField.requestFocus();
textField.selectAll();
}
}
/**
* createTextField creates a TextField to allow editing of data in the Cell.
* It initializes the event handlers for the Escape key and the Enter key.
* It also listens for when it gets unfocused.
*/
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
textField.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.ESCAPE){
cancelEdit();
} else if(event.getCode() == KeyCode.ENTER){
stoppedEditing();
}
});
textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
if(oldValue){
stoppedEditing();
}
});
}
/**
* stoppedEditing gets called whenever a cell leaves editing mode.
* This happens whenever the Enter key gets pressed or when the focus shifts away from the cell.
* If there is no value, it will simple cancel out.
* Otherwise it will propagate the changes to the respective ActivityTreeItem
* and commit the edit to the cell.
*/
private void stoppedEditing(){
try {
if (textField.getText().equals("")) {
cancelEdit();
} else {
if (getTreeTableRow().getTreeItem().getValue() instanceof Activity) {
Activity activityTreeItem = (Activity) getTreeTableRow().getTreeItem().getValue();
activityTreeItem.setActivityDataForDate(Month.valueOf(getTableColumn().getText()).getValue(),
Year.parse(getTableColumn().getParentColumn().getText()).getValue(),
NUMBER_FORMAT.parse(textField.getText()).doubleValue());
}
commitEdit(NUMBER_FORMAT.parse(textField.getText()).doubleValue());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* cancelEdit gets called when the cell stops editing and
* either was left by using the Escape key or there was no new value in the cell
*/
@Override
public void cancelEdit() {
super.cancelEdit();
setText(getFormatted());
setGraphic(null);
}
/*
format into double number for editing in text field
*/
private String getString() {
//return getItem() == null ? "" : NumberFormat.getNumberInstance().format(((double)getItem()));
return getItem() == null ? "" : NUMBER_FORMAT.format(((double)getItem()));
}
/*
format into double number with currency locale
*/
private String getFormatted(){
return getItem() == null ? "" :CURRENCY_FORMAT.format(getItem().doubleValue());
}
}
导入be.vincentnagy.ehka.activity.activity;
导入be.vincentnagy.ehka.category.category;
导入be.vincentnagy.ehka.treetableview.item.CustomTreeItem;
导入be.vincentnagy.ehka.treetableview.item.TotalTreeItem;
导入javafx.geometry.Pos;
导入javafx.scene.control.TextField;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeTableCell;
导入javafx.scene.input.KeyCode;
导入java.text.NumberFormat;
导入java.text.ParseException;
导入java.time.Month;
导入java.time.Year;
/**
*@作者文森特·纳吉
*MoneyFormatCell是TreeTableCell的自定义实现。
*它为特定单元格提供编辑功能
*并将更改传播到基础数据项。
*/
公共类MoneyFormatCell扩展了TreeTableCell{
私有文本字段文本字段;
私有静态final NumberFormat NUMBER_FORMAT=NumberFormat.getNumberInstance();
私有静态最终NumberFormat CURRENCY_FORMAT=NumberFormat.getCurrencyInstance();
静止的{
数字\u格式。setMaximumFractionDigits(2);
数字\u格式。setMinimumFractionDigits(2);
}
公共货币格式单元格(){
}
/**
*每当MoneyFormatCell更改状态时,就会调用updateItem。
*TotalTreeItem和CategoryTreeItem的编辑被禁用。
*提供单元格内用于输入的文本框。
*@param item正在添加到MoneyFormatCell。仅在初始填充表时调用
*@param empty无论单元格是否为空
*/
@凌驾
受保护的void updateItem(数字项,布尔值为空){
super.updateItem(项,空);
设置对齐(位置居中\右侧);
TreeItem TreeItem=getTreeTableRow().getTreeItem();
//如果它是一个叶子,则设置为可编辑(如果它是ActivityDataItem,则称为可编辑)
setEditable(treeItem!=null&&treeItem.isLeaf());
//如果不是总计行且不是类别行,则设置为可编辑
setEditable(!(treeItem!=null&(treeItem.getValue()实例of TotalTreeItem | | treeItem.getValue()实例of Category));
if(空){
setText(空);
设置图形(空);
}否则{
if(isEditing()){
if(textField!=null){
setText(getString());
setText(空);
设置图形(文本字段);
}
}否则{
如果(项==null){
if(textField!=null&&!textField.getText().equals(“”){
停止编辑();
}
setText(“”);
}否则{
setText(NumberFormat.getCurrencyInstance().format(item.doubleValue());
}
设置图形(空);
}
}
}
/**
*startEdit在MoneyFormatCell进入编辑模式时被调用。
*如果尚未创建TextField元素,则会创建该元素
*并将图形从字符串切换到文本字段。
*/
@凌驾
公开作废已启动IT(){
如果(isEditable()){
super.startEdit();
if(textField==null){
createTextField();
}
setText(空);
设置图形(文本字段);
textField.requestFocus();
textField.selectAll();
}
}
/**
*createTextField创建一个TextField以允许编辑单元格中的数据。
*它初始化Escape键和Enter键的事件处理程序。
*它也会在注意力不集中时倾听。
*/
私有void createTextField(){
textField=newtextfield(getString());
textField.setMinWidth(this.getWidth()-this.getGraphicTextGap()*2);
textField.setOnKeyReleased(事件->{
if(event.getCode()==KeyCode.ESCAPE){
取消编辑();
}else if(event.getCode()==KeyCode.ENTER){
停止编辑();
}
});
textField.focusedProperty().addListener((可观察、旧值、新值)->{
如果(旧值){
停止编辑();
}
});
}
/**
*每当单元格离开编辑模式时,都会调用stoppedEditing。
*每当按下Enter键或焦点从单元格移开时,都会发生这种情况。
*如果没有值,它将简单地取消。
*否则,它会将更改传播到相应的ActivityTreeItem
*并将编辑提交到单元格。
*/
私有void stoppedEditing(){
试一试{
if(textField.getText().equals(“”){
取消编辑();
}否则{
if(getTreeTableRow().getTreeItem().getValue()活动实例){
活动activityTreeItem=(活动)getTreeTableRow().getTreeItem().getValue();
activityTreeItem.setActivityDataForDate(Month.valueOf)(getTable
/**
* Create a column for the requested months in the specified year. Doesn't need to start at January.
* Bind the cell to the ActivityTreeItem valueProperty
*
* @param yearColumn The column to initialize
* @param year The year it belongs to
* @param startMonth The starting month in case it's not a full year
* @param endMonth The ending month in case it's not a full year
*/
private void createMonthColumns(TreeTableColumn<CustomTreeItem, Number> yearColumn, int year, int startMonth, int endMonth) {
for (int i = startMonth; i <= endMonth; i++) {
Month month = Month.of(i);
TreeTableColumn<CustomTreeItem, Number> ttc = new TreeTableColumn<>(month.toString());
ttc.setMinWidth(MIN_TABLE_WIDTH);
Month currentMonth = Month.of(i);
ttc.setCellValueFactory(param -> {
if (param.getValue().getValue() instanceof Activity) {
Activity treeItem = (Activity) param.getValue().getValue();
return treeItem.getActivityDataForDate(currentMonth.getValue(), year);
} else if (param.getValue().getValue() instanceof TotalTreeItem) {
TotalTreeItem totalTreeItem = (TotalTreeItem) param.getValue().getValue();
return totalTreeItem.valueProperty(currentMonth.getValue(), year);
}
return null;
});
ttc.setCellFactory(param -> new MoneyFormatCell());
yearColumn.getColumns().add(ttc);
}
}