【问题标题】:JavaFX Table Cell EditingJavaFX 表格单元格编辑
【发布时间】:2014-09-04 03:41:51
【问题描述】:

我正在尝试用 Java 编写一个程序来管理我的 bookie 帐户。我是java新手,所以我想我会选择一些简单的东西来看看事情是如何工作的。我决定使用 tableview 并使单个单元格可编辑。我一直在关注本教程http://java-buddy.blogspot.co.uk/2012/04/javafx-2-editable-tableview.html。它详细介绍了如何使用 java 代码来完成它,并将其复制到一个新类中效果很好。我决定尝试调整它以使用 FXML,因为我喜欢 Sceneviewer。我的问题是,数据已加载到表格中,但是当我单击/双击一个单元格时,没有任何反应。这是我的代码。

testController.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();
    }
}
}

这是我的 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);
    }

}

最后,这是我的 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>

正如我之前所说,单击“用户名”单元格时没有任何反应。没有错误,没有文本字段,什么都没有。 任何帮助将不胜感激!谢谢

【问题讨论】:

    标签: java javafx tableview scenebuilder


    【解决方案1】:

    我没有尝试过您的示例,但我认为您只是忘记为特定列设置 cellFactory。添加以下行应该可以解决它:

    usernameCol.setCellFactory(cellFactory);
    

    【讨论】:

    • 没错,但您还需要修复类型(Callback&lt;TableColumn&lt;Account, String&gt;, TableCell&lt;Account, String&gt;&gt; 等)。这种方法有点遗留:你可以做usernameCol.setCellFactory(TextFieldTableCell.forTableColumn());并摆脱EditingCell
    • 好的,谢谢,我现在就试试。不幸的是,javafx 和可编辑表的教程并不多:(
    • 这不是很好,但default Oracle tutorial 涵盖了基础知识。
    • 效果很好,我也删除了编辑单元类!代码更少,我更容易理解!谢谢。
    • @OrdinaryDraft 你可能想看看这里:stackoverflow.com/questions/24694616/…。我面临着同样的挑战,不幸的是,这并不是一件容易的事情。不确定是否有更好的方法,但 kleopatra 能够提供体面的解决方法。
    【解决方案2】:

    您可以使用 :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);
    

    【讨论】:

      【解决方案3】:

      如果有人需要一个工作示例,我可以通过添加一个

      来让代码与 this tutorial 一起使用
      usernameCol.setCellFactory(
                      TextFieldTableCell.forTableColumn());
      

      并将usernameCol.setOnEditCommit 更改为

      usernameCol.setOnEditCommit(
                      (TableColumn.CellEditEvent<Account, String> t) ->
                          ( t.getTableView().getItems().get(
                                  t.getTablePosition().getRow())
                          ).setFieldUsername(t.getNewValue())
                      );
      

      这里是完整的 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);
      
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多