使用FXML(JavaFX)的按钮表

时间:2014-11-15 11:03:14

标签: java button javafx fxml

我正在学习JavaFX和FXML。我正在使用Oracle网站上提供的教程。

特别是,我正在使用FXML地址簿的Oracle示例作为起点(https://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI)开发应用程序。我现在要做的是添加一个列,其中包含与电话簿的每个条目相关联的按钮。例如,单击的按钮在另一个表上显示有关该名称条目的更多数据。我想用FXML做这件事。在网上搜索我发现了一些关于如何创建按钮列的资源,但它们看起来有点令人困惑,似乎他们没有使用FXML,这正是我所需要的。

有人可以建议我一些教程或提示吗?

编辑:我按照本教程(https://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI)开始工作。我想要做的部分内容在此处描述:JavaFX table- how to add components?。但是,这个例子并没有使用fxml。我想要做的是混合代码。 所以,我有一个fxml文件(取自上面链接的oracle教程),声明这个表,这样:

    <TableView fx:id="tableView" GridPane.columnIndex="0" 
    GridPane.rowIndex="0">
    <columns>
        <TableColumn fx:id="Names_column" text="Table" prefWidth="100">
            <cellValueFactory><PropertyValueFactory property="name" />
            </cellValueFactory>
            <cellFactory>
                <FormattedTableCellFactory alignment="center">                        
                </FormattedTableCellFactory>
            </cellFactory>
        </TableColumn>

        <TableColumn text="Color" prefWidth="100">
            <cellValueFactory><PropertyValueFactory property="color" />
            </cellValueFactory>                
        </TableColumn>  

        <TableColumn text="Button" prefWidth="100">          
        </TableColumn>                                  
    </columns>

    <items>
        <FXCollections fx:factory="observableArrayList">
            <ColTab name="Table 1" color="1"   />  
            <ColTab name="Table 2" color="2"   />
            <ColTab name="Table 3" color"1"   />
        </FXCollections>
    </items>

</TableView>

然后,我看了另一个例子(JavaFX table- how to add components?)。在这个例子中,一切都只使用Java,但出于我的目的,我需要使用fxml。 在我的.java主文件中,我这样做了:

       TableColumn<ColTab, ColTab> btnCol = new TableColumn<>("pulsanti");
   btnCol.setMinWidth(150);
   btnCol.setCellValueFactory(new Callback<CellDataFeatures<ColTab, ColTab>, ObservableValue<ColTab>>() {
      @Override public ObservableValue<ColTab> call(CellDataFeatures<ColTab, ColTab> features) {
          return new ReadOnlyObjectWrapper(features.getValue());     
      }
    });

    btnCol.setCellFactory(new Callback<TableColumn<ColTab, ColTab>, TableCell<ColTab, ColTab>>() {
      @Override public TableCell<ColTab, ColTab> call(TableColumn<ColTab, ColTab> btnCol) {
        return new TableCell<ColTab, ColTab>() {              
          final Button button = new Button(); {              
            button.setMinWidth(130);
          }
          @Override public void updateItem(final ColTab ColTab, boolean empty) {
            super.updateItem(ColTab, empty);
            if (ColTab != null) {
                  button.setText("Do something");

              button.setOnAction(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent event) {
                  //do something
                }
              });
            }
          }
        };
      }
    });

    //table.getColumns().addAll(firstNameCol, lastNameCol, emailCol, btnCol);

此代码是从我链接的第二个示例中复制的,实际上对我来说并不太清楚。我看到它创建了一个新列并设置了一些属性。最后一行代码(注释掉)将此列和其他一些列添加到一个表中,该表先前在原始.java文件中声明,并且我没有声明,因为我已经在表中声明了fxml文件。现在我正在寻找一种方法来集成我在.java文件中定义的这一列,在我在.fxml文件中声明的表中。 我知道我所说的可能看起来很混乱,但我对JavaFX和fxml并不熟悉,并不是所有的细节都清楚。

EDIT2: 我的控制器代码如下所示:

public class FXMLDocumentController implements Initializable {

@FXML
private TableView<ColTab> tableView;    
tableView.getColumns().add(btnCol); 


@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    

}

现在我收到一条错误消息:

  

包tableView不存在

     

预期的标识符

     

&#39 ;;&#39;预期

我使用Netbeasn作为ide。

1 个答案:

答案 0 :(得分:1)

您可以将复制的代码放入控制器的initialize方法中。您已经在桌面上定义了fx:id=tableView属性,因此我假设您有

@FXML
private TableView<ColTab> tableView ;

在控制器中。只需使用

将额外的列添加到表视图中
tableView.getColumns().add(btnCol);

要了解如何配置此列,您需要了解表中显示的数据与数据的视图之间存在分离(即向用户呈现数据)。在JavaFX中,对于复杂的UI控件(如表,树和列表),数据视图由单元格表示。您在列上设置的单元工厂告诉JavaFX如何从单元格中显示的数据创建TableCell - 它本质上是一个在需要时创建TableCell的函数。首次创建单元格时,以及数据更改时,都会调用单元格的updateItem(..)方法。

updateItem(...)方法中的逻辑不太正确。首先,您需要通过调用单元格的setGraphic(...)方法实际显示单元格中的按钮。其次,您需要处理单元格为空的情况(即该项为空)。所以我会做这样的事情:

btnCol.setCellFactory(new Callback<TableColumn<ColTab, ColTab>, TableCell<ColTab, ColTab>>() {
  @Override public TableCell<ColTab, ColTab> call(TableColumn<ColTab, ColTab> btnCol) {
    final Button button = new Button();
    button.setMinWidth(130);
    TableCell<ColTab, ColTab> cell = new TableCell<ColTab, ColTab>() {              
      @Override public void updateItem(final ColTab ColTab, boolean empty) {
        super.updateItem(ColTab, empty);
        if (ColTab == null) {
            setGraphic(null);
        } else {
            button.setText("Do something");
            setGraphic(button);
        }

      }
    };

    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent event) {
          ColTab currentItem = cell.getItem();
          //do something with current item...
        }
    });

    return cell ;
  }
});

您可以在Cell JavadocsTableView Javadocs中详细了解有关细胞机制的信息。 tutorial for ListViewTableView也可以提供帮助。

单元格值工厂告诉表格如何从该行的数据中获取特定单元格的数据。在这种情况下,这有点微妙。该按钮取决于整行的数据(因为它将在其动作处理程序中需要这些数据),因此它只返回行数据对象周围的包装器。上面链接的TableColumn Javadocs和表格教程谈到了这一点。