简体   繁体   English

使用FXML(JavaFX)的带有按钮的表

[英]Table with buttons using FXML (JavaFX)

I am learning JavaFX and FXML. 我正在学习JavaFX和FXML。 I am using the tutorials available on the Oracle website. 我正在使用Oracle网站上的教程。

In particular, I am developing an application using the Oracle example of an FXML Address Book as a starting point ( https://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI ). 特别是,我正在使用FXML通讯簿的Oracle示例作为起点来开发应用程序( https://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI )。 What I want to do now, is to add a column with a button associated with each entry of the phone book. 我现在想做的是添加一列带有与电话簿中每个条目相关联的按钮的按钮。 For example, a button that when clicked shows, on another table, more data regarding that name entry. 例如,单击一个按钮会在另一个表上显示有关该名称条目的更多数据。 I want to do this using FXML. 我想使用FXML做到这一点。 Searching the web I found some resources on how to create a button column, but they look kind of confusing and it seems they don't use FXML, which is what I need. 在网络上搜索时,我发现了一些有关如何创建按钮列的资源,但是它们看上去有点令人困惑,并且似乎他们没有使用FXML,这正是我所需要的。

Anybody can suggest me some tutorial or hint? 有人可以建议我一些教程或提示吗?

Edit: I started my work following this tutorial ( https://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI ). 编辑:我按照本教程( https://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI )开始工作。 Part of what I want to do, is described here: JavaFX table- how to add components? 我要做的部分工作在此处进行了描述: JavaFX表-如何添加组件? . However, this example doesn't make use of fxml. 但是,此示例未使用fxml。 What I am trying to do is mixing the codes. 我正在尝试混合代码。 So, I have a fxml file (taken from the oracle tutorial linked above) where the table is declared, this way: 因此,我有一个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>

Then, I took a look at the other example ( JavaFX table- how to add components? ). 然后,我看了另一个示例( JavaFX表-如何添加组件? )。 In this example, everything is made only using Java, but for my purpose, I need to use fxml. 在此示例中,一切都仅使用Java进行,但是出于我的目的,我需要使用fxml。 In my .java main file, I did this: 在我的.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);

This code is copied from the second example I linked, and actually is not too clear to me. 这段代码是从我链接的第二个示例复制而来的,实际上对我来说不太清楚。 What I see is that it creates a new column and sets some properties. 我看到的是它将创建一个新列并设置一些属性。 The last line of code (commented out) adds this column, and some other ones, to a table, which was previously declared in the original .java file and which I didn't declare, since I already declared the table in the fxml file. 代码的最后一行(注释掉)将此列和其他一些列添加到表中,该表先前已在原始.java文件中声明,但由于我已经在fxml文件中声明了该表,所以未声明。 Now I am looking for a way to integrate this column that I am defining in the .java file, in the table that I declare in my .fxml file. 现在,我正在寻找一种方法,以将在.java文件中定义的此列集成到在.fxml文件中声明的表中。 I know that what i am saying might look very messy, but I am really new to JavaFX and fxml, and not all the details are clear to me. 我知道我说的话看起来很凌乱,但是我对JavaFX和fxml确实很陌生,并不是所有细节都对我很清楚。

Edit2: My code for the controller looks like this: Edit2:我的控制器代码如下所示:

public class FXMLDocumentController implements Initializable {

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


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

}

Now I am getting an error that says: 现在我收到一个错误消息:

package tableView does not exist 包tableView不存在

identifier expected 预期的标识符

';' ';' expected 预期

I am using Netbeasn as ide. 我使用Netbeasn作为ide。

You can just put the code you copied into the initialize method of your controller. 您可以将复制的代码放入控制器的initialize方法中。 You have already defined an fx:id=tableView attribute on your table, so I assume you have 您已经在表上定义了fx:id=tableView属性,所以我认为您已经

@FXML
private TableView<ColTab> tableView ;

in the controller. 在控制器中。 Just add the extra column to the table view with 只需添加额外的列到表视图中

tableView.getColumns().add(btnCol);

To understand how this column is being configured, you need to understand that there is a separation between the data displayed in the table, and the view of the data (ie the presentation of the data to the user). 要了解如何配置此列,您需要了解表中显示的数据数据 视图 (即,向用户呈现数据)之间存在分隔。 In JavaFX, for complex UI controls such as tables, trees, and lists, the view of the data is represented by a cell. 在JavaFX中,对于复杂的UI控件(例如表,树和列表),数据视图由单元格表示。 The cell factory that you set on a column tells JavaFX how to create a TableCell from the data displayed in the cell - it's essentially a function that creates TableCell s when needed. 您设置列的单元格工厂告诉JavaFX的如何创建一个TableCell从单元格中显示的数据-这是本质上创建了一个函数TableCell需要时秒。 The cell's updateItem(..) method is called when the cell is first created, and any time the data changes. 首次创建单元格时以及数据更改时,将调用该单元格的updateItem(..)方法。

The logic in your updateItem(...) method is not quite correct. 您的updateItem(...)方法中的逻辑不太正确。 First, you need to actually display the button in the cell, by calling the cell's setGraphic(...) method. 首先,您需要通过调用单元格的setGraphic(...)方法在单元格中实际显示按钮。 Second, you do need to handle the case where the cell is empty (ie the item is null). 其次,您确实需要处理单元格为空(即项目为null)的情况。 So I would do something like this: 所以我会做这样的事情:

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 ;
  }
});

You can read more about the cell mechanism in general in the Cell Javadocs and the TableView Javadocs . 您可以在Cell JavadocsTableView Javadocs中阅读一般有关单元机制的更多信息。 The tutorial for ListView and TableView may also help. ListViewTableView教程也可能会有所帮助。

The cell value factory tells the table how to get the data for a particular cell from the data for that row. 单元格的值工厂告诉表格如何让数据从该行的数据中的特定细胞。 In this case this is a bit subtle. 在这种情况下,这有点微妙。 The button depends on the data for the whole row (because it will need those data in its action handler), so it just returns a wrapper around the row data object. 该按钮取决于整个行的数据(因为它将在其动作处理程序中需要这些数据),因此它仅返回围绕行数据对象的包装器。 The TableColumn Javadocs and the table tutorial linked above talk about this. TableColumn Javadocs和上面链接的表教程对此进行了讨论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM