我有TableView
通过单个单元格编辑接受数据。现在我还想通过粘贴文件来输入数据,如下所示。
11.12 23.32 15.43
22.23 24.45 26.65
我想使用说CTRL+V
来粘贴数据。我已经看过post in StackOverflow或the GIT repo等帖子。我无法粘贴多行数据。
这里我给出了主要代码。
package testmatrix;
import javafx.application.Application;
import javafx.collections.*;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.*;
import javafx.scene.control.cell.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class TestMATRIX extends Application {
TableView<CommonDataClass> matrixData = new TableView<CommonDataClass>();
final ObservableList<CommonDataClass> matData = FXCollections.
observableArrayList();
TableColumn[] matrixDataColumns = new TableColumn[6];
int numColVal = 0;
int theNDX = 0;
int maxRowNum = 0;
TextField TC1 = new TextField();
TextField TC2 = new TextField();
TextField TC3 = new TextField();
TextField TC4 = new TextField();
TextField TC5 = new TextField();
TextField TC6 = new TextField();
boolean numColStatus = false;
int oldRowVal = 0;
int oldColVal = 0;
boolean newRow = false;
boolean newCol = false;
@Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
TextField myTextField = new TextField();
Label colL = new Label("Column Number->");
TextField colNumT = new TextField();
Button getNum = new Button("SET");
colNumT.setMaxWidth(40);
TableUtils.doCopyPasteHandler (matrixData, matData);
matrixData.setVisible(true);
matrixData.setEditable(true);
matrixData.getSelectionModel().setCellSelectionEnabled(true);
matrixData.getSelectionModel ().setSelectionMode (SelectionMode.MULTIPLE);
HBox hb1 = new HBox();
HBox hb2 = new HBox();
hb1.getChildren().add(matrixData);
hb2.getChildren().addAll(colL, colNumT, getNum);
root.setCenter(hb1);
root.setRight(hb2);
getNum.addEventHandler(ActionEvent.ACTION, e -> {
numColStatus = (colNumT.getText().isEmpty()) ? false : true;
numColVal = (numColStatus) ? Integer.parseInt(colNumT.getText()): 0;
if (numColStatus) {
addRowBelow();
matrixData.getColumns ().clear ();
for (int ii = 0; ii < numColVal; ii++) {
matrixDataColumns[ii] = createCol(ii);
editCommit(ii);
}
matrixData.setItems(matData);
if (numColStatus) {
for (int ii = 0; ii < numColVal; ii++) {
matrixData.getColumns().add(matrixDataColumns[ii]);
}
}
matrixData.refresh();
}
});
Scene scene = new Scene(root, 1200, 400);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
TableColumn<CommonDataClass, String> createCol(int icol) {
TableColumn<CommonDataClass, String> column = new TableColumn<>();
column.setMinWidth(30);
column.setStyle(
"-fx-alignment: CENTER-RIGHT;-fx-font-family: monospace; -fx-font-size: 10px; ");
String nameC = "myD" + (icol + 1);
System.out.println("colName->" + nameC);
column.setCellValueFactory(
new PropertyValueFactory<CommonDataClass, String>(nameC));
column.setCellFactory(
new DragSelectionCellFactory<CommonDataClass, String>(TextFieldTableCell.forTableColumn()
)
);
column.setMinWidth(120);
return column;
}
private void editCommit(int ii) {
System.out.println("Command came here");
matrixDataColumns[ii].setOnEditCommit(
new EventHandler<CellEditEvent<CommonDataClass, String>>() {
@Override
public void handle(CellEditEvent<CommonDataClass, String> event) {
int colNum = event.getTablePosition().getColumn();
switch (colNum) {
case 0:
event.getTableView().getItems().get(event.getTablePosition().getRow()).setMyD1(event.getNewValue());
break;
case 1:
event.getTableView().getItems().get(event.getTablePosition().getRow()).setMyD2(event.getNewValue());
break;
case 2:
event.getTableView().getItems().get(event.getTablePosition().getRow()).setMyD3(event.getNewValue());
break;
case 3:
event.getTableView().getItems().get(event.getTablePosition().getRow()).setMyD4(event.getNewValue());
break;
case 4:
event.getTableView().getItems().get(event.getTablePosition().getRow()).setMyD5(event.getNewValue());
break;
case 5:
event.getTableView().getItems().get(event.getTablePosition().getRow()).setMyD6(event.getNewValue());
break;
}
matrixData.setItems(matData);
matrixData.refresh();
if (!event.getNewValue().isEmpty()) {
addRowBelow();
}
}
});
}
void addRowBelow() {
matData.add(new CommonDataClass(
TC1.getText(), TC2.getText(), TC3.getText(),
TC4.getText(), TC5.getText(), TC6.getText()
));
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
这里我展示了TableView
的数据结构。
package testmatrix;
import javafx.beans.property.*;
public class CommonDataClass {
private final SimpleStringProperty myD1;
private final SimpleStringProperty myD2;
private final SimpleStringProperty myD3;
private final SimpleStringProperty myD4;
private final SimpleStringProperty myD5;
private final SimpleStringProperty myD6;
public CommonDataClass(String myStr1, String myStr2, String myStr3, String myStr4, String myStr5, String myStr6) {
this.myD1 = new SimpleStringProperty(myStr1);
this.myD2 = new SimpleStringProperty(myStr2);
this.myD3 = new SimpleStringProperty(myStr3);
this.myD4 = new SimpleStringProperty(myStr4);
this.myD5 = new SimpleStringProperty(myStr5);
this.myD6 = new SimpleStringProperty(myStr6);
}
public String getMyD1(){
return myD1.get();
}
public String getMyD2(){
return myD2.get();
}
public String getMyD3(){
return myD3.get();
}
public String getMyD4(){
return myD4.get();
}
public String getMyD5(){
return myD5.get();
}
public String getMyD6(){
return myD6.get();
}
public void setMyD1(String myStr){
myD1.set(myStr);
}
public void setMyD2(String myStr){
myD2.set(myStr);
}
public void setMyD3(String myStr){
myD3.set(myStr);
}
public void setMyD4(String myStr){
myD4.set(myStr);
}
public void setMyD5(String myStr){
myD5.set(myStr);
}
public void setMyD6(String myStr){
myD6.set(myStr);
}
public StringProperty dataNameProperty(int index) {
StringProperty strProp = null;
switch (index) {
case 0:
strProp = myD1;
break;
case 1:
strProp = myD2;
break;
case 2:
strProp = myD3;
break;
case 3:
strProp = myD4;
break;
case 4:
strProp = myD5;
break;
case 5:
strProp = myD6;
break;
}
return strProp;
}
}
我在这里给出了DrageSelection
单元格的代码。
package testmatrix;
import javafx.scene.control.TableCell;
import javafx.scene.input.*;
public class DragSelectionCell extends TableCell<CommonDataClass, String> {
public DragSelectionCell() {
setOnDragDetected ((MouseEvent event) -> {
startFullDrag ();
getTableColumn ().getTableView ().getSelectionModel ().select (
getIndex (), getTableColumn ());
});
setOnMouseDragEntered ((MouseDragEvent event) -> {
getTableColumn ().getTableView ().getSelectionModel ().select (
getIndex (), getTableColumn ());
});
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem (item, empty);
if ( empty ) {
setText (null);
} else {
setText (item);
}
}
}
我在这里给出DragSelectionCellfactory
代码。
package testmatrix;
import javafx.scene.control.*;
import javafx.util.Callback;
public class DragSelectionCellFactory<CommonDataClass, String> implements
Callback<TableColumn<CommonDataClass, String>, TableCell<CommonDataClass, String>> {
private final Callback<TableColumn<CommonDataClass, String>, TableCell<CommonDataClass, String>> factory;
public DragSelectionCellFactory(
Callback<TableColumn<CommonDataClass, String>, TableCell<CommonDataClass, String>> factory) {
this.factory = factory;
}
public DragSelectionCellFactory() {
this (col -> new TableCell<CommonDataClass, String> () {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem (item, empty);
if ( empty || item == null ) {
setText (null);
} else {
setText (item.toString ());
}
}
});
}
@Override
public TableCell<CommonDataClass, String> call(
final TableColumn<CommonDataClass, String> col) {
TableCell<CommonDataClass, String> cell = factory.call (col);
cell.setOnDragDetected (event -> {
cell.startFullDrag ();
col.getTableView ().getSelectionModel ().select (cell.getIndex (),
col);
});
cell.setOnMouseDragEntered (event -> {
col.getTableView ().getSelectionModel ().select (cell.getIndex (),
col);
});
cell.setOnMouseEntered (e -> {
String item = cell.getItem ();
if ( item != null ) {
}
});
return cell;
}
}
以下代码块描述类似于开头所述的复制/粘贴例程的表实用程序。但是,粘贴部分不起作用,所以我试图修改。现在我完全糊涂了。复制部分正在复制,而上面引用中显示的粘贴部分无法粘贴所有行和列。
package testmatrix;
import java.util.StringTokenizer;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.event.EventHandler;
import javafx.scene.control.*;
import javafx.scene.input.*;
public class TableUtils extends TableCell<CommonDataClass, String> {
ObservableList<CommonDataClass> datTab = FXCollections.
observableArrayList ();
public static void doCopyPasteHandler(TableView<?> table,
ObservableList<CommonDataClass> myData) {
table.setOnKeyPressed (new TableKeyEventHandler ());
}
public static class TableKeyEventHandler implements EventHandler<KeyEvent> {
KeyCodeCombination copyCode = new KeyCodeCombination (KeyCode.C,
KeyCodeCombination.CONTROL_ANY);
KeyCodeCombination pasteCode = new KeyCodeCombination (KeyCode.V,
KeyCodeCombination.CONTROL_ANY);
//@Override
public void handle(KeyEvent event) {
if ( copyCode.match (event) ) {
if ( event.getSource () instanceof TableView ) {
copySelection2Clipboard ((TableView<?>) event.getSource ()); // this will copy to clipboard
event.consume (); // After using event please consume
}
} else if ( pasteCode.match (event) ) {
if ( event.getSource () instanceof TableView ) {
pasteFromClipboard ((TableView<?>) event.getSource ());
event.consume ();
}
}
}
}
public static void copySelection2Clipboard(TableView<?> table) {
StringBuilder clipboardString = new StringBuilder ();
ObservableList<TablePosition> positionList = table.getSelectionModel ().
getSelectedCells ();
int prevRow = -1;
for ( TablePosition pos : positionList ) {
int row = pos.getRow ();
int col = pos.getColumn ();
if ( prevRow == row ) { // determine whether we advance in a row or col (newline)
clipboardString.append ('\t');
} else if ( prevRow != -1 ) {
clipboardString.append ('\n');
}
String text = "";
Object obsValue = (Object) table.getColumns ().get (col).
getCellObservableValue (row);
if ( obsValue == null ) {
text = "";
} else if ( obsValue instanceof StringProperty ) {
text = ((StringProperty) obsValue).get ();
} else {
System.out.println ("Unsupported observable value: " + obsValue);
}
clipboardString.append (text);
prevRow = row;
}
ClipboardContent clipboardContent = new ClipboardContent ();
clipboardContent.putString (clipboardString.toString ());
}
public static void pasteFromClipboard(TableView<?> table) {
if ( table.getSelectionModel ().getSelectedCells ().size () == 0 ) {
return;
}
TablePosition pasteCellPosition = table.getSelectionModel ().
getSelectedCells ().get (0); // get cell position at start
String pasteString = Clipboard.getSystemClipboard ().getString ();
StringTokenizer rowTokenizer = new StringTokenizer (pasteString, "\n");
int rowNum = rowTokenizer.countTokens () + 1;
int rowCB = -1;
while (rowTokenizer.hasMoreTokens ()) {
rowCB++;
String rowString = rowTokenizer.nextToken ();
StringTokenizer colTokenizer = new StringTokenizer (rowString, "\t");
int colCB = -1;
while (colTokenizer.hasMoreTokens ()) {
colCB++;
String clpCellCont = colTokenizer.nextToken ();
int rowTable = pasteCellPosition.getRow () + rowCB;
int colTable = pasteCellPosition.getColumn () + colCB;
if ( rowTable >= table.getItems ().size () ) {
continue;
}
if ( colTable >= table.getColumns ().size () ) {
continue;
}
TableColumn tabCol = table.getVisibleLeafColumn (colTable);
ObservableValue obsVal = tabCol.
getCellObservableValue (rowTable);
}
}
}
}
如果我得到任何帮助,那将会有很大的帮助。谢谢和问候
答案 0 :(得分:1)
由于事件处理程序中没有代码,因此无法插入值。
此外,您不使用属性,这会使事情变得更复杂。
如果您使用属性
TableColumn<CommonDataClass, String> createCol(int icol) {
...
column.setCellValueFactory(
cd -> cd.getValue().dataNameProperty(icol));
您可以使用属性分配新值:
public static <T> void pasteFromClipboard(TableView<T> table) {
if (table.getSelectionModel().getSelectedCells().isEmpty()) {
return;
}
TablePosition pasteCellPosition = table.getSelectionModel().
getSelectedCells().get(0); // get cell position at start
Clipboard cb = Clipboard.getSystemClipboard();
// check, if clipboard contains a string
if (!cb.hasString()) {
return;
}
String pasteString = cb.getString();
String[][] values = Stream.of(pasteString.split("\r?\n"))
.map(line -> line.split("\t")).toArray(String[][]::new);
final int offsetY = pasteCellPosition.getRow();
final int offsetX = pasteCellPosition.getColumn();
final int maxY = Math.min(table.getItems().size() - offsetY, values.length);
final int colMax = table.getColumns().size() - offsetX;
for (int y = 0; y < maxY; y++) {
String[] r = values[y];
final int maxX = Math.min(colMax, r.length);
T rowObject = table.getItems().get(y+offsetY);
for (int x = 0; x < maxX; x++) {
Object property = table.getColumns().get(x + offsetX).getCellObservableValue(rowObject);
if (property instanceof StringProperty) {
// write value using the property
((StringProperty) property).set(r[x]);
}
}
}
}
这只会将值插入现有行...
但请注意,您应该在DragSelectionCellFactory
类中使用命名约定,即使用单个字母作为类型参数的名称。在您的情况下,类型参数名为CommonDataClass
和String
,即现有类的名称,这几乎肯定会导致混淆......
可能你应该删除类型参数:
public class DragSelectionCellFactory implements
Callback<TableColumn<CommonDataClass, String>, TableCell<CommonDataClass, String>> {
此外,复制内容无效,因为您忘记设置剪贴板内容:
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(clipboardString.toString());
Clipboard.getSystemClipboard().setContent(clipboardContent);
此外,无法保证所选单元格位于矩形区域内。可以通过按住 Ctrl 来任意选择单元格。
另外
getNum.addEventHandler(ActionEvent.ACTION, e -> {...});
可以(并且在这种情况下,恕我直言)应该用
替换getNum.setOnAction(e -> {...});