【发布时间】:2019-08-15 06:13:21
【问题描述】:
我想使用箭头/输入键来遍历TableView 中的单元格,但是,如果我尝试在我的自定义 EditCell 类中实现它,它似乎不起作用。有没有办法做到这一点?我在TextField 上尝试了一个监听器,但它实际上并没有在实际单元格中启动焦点。
这是我的代码:
Tester.java
package tester;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class Tester extends Application
{
@Override
public void start(Stage primaryStage)
{
TableView<LineItem> table = new TableView<>();
Callback<TableColumn<LineItem, String>, TableCell<LineItem, String>> textFactoryEditable = (TableColumn<LineItem, String> p) -> new EditableTextCell();
TableColumn<LineItem, String> column1 = new TableColumn<>("Test1");
column1.setCellValueFactory(cellData -> cellData.getValue().getString1Property());
column1.setEditable(true);
column1.setCellFactory(textFactoryEditable);
table.getColumns().add(column1);
TableColumn<LineItem, String> column2 = new TableColumn<>("Test2");
column2.setCellValueFactory(cellData -> cellData.getValue().getString2Property());
column2.setEditable(true);
column2.setCellFactory(textFactoryEditable);
table.getColumns().add(column2);
table.getItems().add(new LineItem());
table.getItems().add(new LineItem());
table.getItems().add(new LineItem());
table.setPrefWidth(500);
HBox root = new HBox();
root.getChildren().addAll(table);
Scene scene = new Scene(root, 500, 500);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
LineItem.java
package tester;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class LineItem
{
private final StringProperty string1;
private final StringProperty string2;
public LineItem()
{
this.string1 = new SimpleStringProperty();
this.string2 = new SimpleStringProperty();
}
public final StringProperty getString1Property()
{
return this.string1;
}
public final StringProperty getString2Property()
{
return this.string2;
}
}
EditableTextCell.java
package tester;
import java.util.Objects;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WritableValue;
import javafx.geometry.Pos;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
public class EditableTextCell<E> extends TableCell<E, String>
{
private final TextField textField;
private boolean updating = false;
public EditableTextCell()
{
textField = new TextField();
textField.setAlignment(Pos.CENTER_RIGHT);
textField.textProperty().addListener((ObservableValue<? extends String> o, String oldValue, String newValue) ->
{
if (!updating)
{
((WritableValue<String>) getTableColumn().getCellObservableValue((E) getTableRow().getItem())).setValue(newValue);
getTableView().scrollTo(getTableRow().getIndex());
getTableView().scrollToColumn(getTableColumn());
}
});
textField.setOnKeyPressed((KeyEvent ke) ->
{
switch (ke.getCode())
{
case DOWN:
getTableView().getFocusModel().focusBelowCell();
break;
case UP:
getTableView().getFocusModel().focusAboveCell();
break;
case RIGHT:
getTableView().getFocusModel().focusRightCell();
break;
case LEFT:
getTableView().getFocusModel().focusLeftCell();
break;
default:
break;
}
});
}
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (empty)
{
setGraphic(null);
} else
{
setGraphic(textField);
if (!Objects.equals(textField.getText(), item))
{
// prevent own updates from moving the cursor
updating = true;
textField.setText(item);
updating = false;
}
}
}
}
【问题讨论】:
-
尚未深入分析您的代码,但我注意到enable cell selection 似乎没有您。默认情况下,
TableView处于“行选择”模式。 -
谢谢,成功了。现在我能够在 FocusProperty 上添加一个监听器,你能告诉我这是否是最好的方法吗?它似乎正在工作......
-
@kleopatra
TableView应该支持“始终编辑”单元格,根据其文档:“您可以选择单元格是否永久处于编辑状态 [...] ,或在编辑开始时切换到不同的 UI [...]"。不幸的是,使用普通的编辑 API 似乎无法做到这一点——至少不简单。如果你看一下CheckBoxTableCell的实现,你会发现它的作用类似于 OP 的作用。 -
@Slaw 好点 :) 并且有趣(阅读:从未真正见过它
),尽管在 tableView 和 checkBoxTableCell 的文档中没有完全指定(或有些矛盾)在编辑中永久状态 vs. 不需要进入编辑状态 ... -
不相关:您没有遵循 LineItem 中的 fx 命名约定 - 属性访问器应该是
Property(与 get Property)