本文介绍了当使用TableColumn< S,T& gt;时,为什么编译器会生成未经检查的警告而不是TableColumn< S,<>在JavaFX8 TableView中选择一个单元格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个相对的Java新手问题.

A relative Java newbie question.

我正在清理代码,并在以编程方式选择 TableView .我能够解决警告,但不知道是什么原因引起的.

I'm cleaning up my code and came across two unchecked warnings ("unchecked method invocation" and "unchecked conversion") while programmatically selecting a cell in a TableView. I was able to resolve the warnings but don't understand what caused them.

这就是我最初对 select()进行编码的方式:

This was how I initially coded the select():

TablePosition<?, ?> previousPos;
//...
table.getSelectionModel().select
    (previousPos.getRow(), previousPos.getTableColumn());

我通过将其更改为警告来解决了警告.

and I resolved the warnings by changing it to this.

table.getSelectionModel().select
    (previousPos.getRow(), table.getColumns().get(previousPos.getColumn()));

我不了解它们之间的区别,因此我看了一下Java源代码.如果我正确地解释了它,则 TableView.java 中的 select()方法需要 TableColumn< S,?> .但是, TablePosition.java 中的 getTableColumn()返回 TableColumn< S,T> ,而中的 getColumns()em> TableView.java 返回类型为 TableColumn(S,?) ObservableList .

I didn't understand the difference so I had a look at the Java source code. If I'm interpreting it correctly, the select() method in TableView.java expects TableColumn<S, ?>. However, getTableColumn() in TablePosition.java returns TableColumn<S,T> while getColumns() in TableView.java returns an ObservableList of type TableColumn(S, ?).

我想这就是为什么 table.getColumns().get(...)编译干净并且 previousPos.getTableColumn()产生错误的原因.

I guess that's why table.getColumns().get(...) compiles clean and previousPos.getTableColumn() generates errors.

但是,从编译器的角度来看, TableColumn< S,?> TableColumn< S,T> 之间有什么区别?为什么它不解析(这是正确的术语?)将 T 转换为?.

But what is the difference, then, between TableColumn<S, ?> and TableColumn<S,T> from the compiler's point of view? Why doesn't it resolve (is that the correct term?) the T to ?.

如果有帮助,这里是我正在尝试解决的MVCE,但答案超出了我目前的Java知识. select()位于 moveToPreviousPos()中.

If it helps, here is the MVCE I was playing with to try and figure it out, but the answer is beyond my current Java knowledge. The select() is in moveToPreviousPos().

我正在使用JavaFX8(JDK1.8.0_181),NetBeans 8.2和Scene Builder 8.3.

I'm using JavaFX8 (JDK1.8.0_181), NetBeans 8.2 and Scene Builder 8.3.

package test27;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Test27 extends Application {

    TableView<TestModel> table = new TableView<>();

    //Both of these stop the "unchecked conversion" error on line #51 (previousPos = table.getFocusModel().getFocusedCell();)
    //    TablePosition previousPos;
        TablePosition<?, ?> previousPos;
    //but using the following generates the "unchecked conversion" error
    //    TablePosition<TestModel, ?> previousPos;

    private Parent createContent() {

        ObservableList<TestModel> olTestModel = FXCollections.observableArrayList();

        olTestModel.add(new TestModel("A"));
        olTestModel.add(new TestModel("B"));
        olTestModel.add(new TestModel("C"));

        table.setItems(olTestModel);

        TableColumn<TestModel, String> colText = new TableColumn<>("text");
        colText.setCellValueFactory(cellData -> cellData.getValue().textProperty());
        colText.setCellFactory(TextFieldTableCell.forTableColumn());

        table.getSelectionModel().setCellSelectionEnabled(true);
        table.setEditable(true);
        table.getColumns().add(colText);

        Button btnGetTablePosition = new Button("get table position");
        btnGetTablePosition.setOnAction(event -> {
            //TableView.java:  getFocusedCell returns TablePosition<S, ?>
            previousPos = table.getFocusModel().getFocusedCell(); //Line #51
            outputPreviousPos(previousPos);
        });

        Button btnMoveToPreviousPos = new Button("move to previous pos");
        btnMoveToPreviousPos.setOnAction(event -> {
            moveToPreviousPos(previousPos);
        });

        BorderPane content = new BorderPane(table);
        HBox hb = new HBox();
        hb.getChildren().addAll(btnGetTablePosition, btnMoveToPreviousPos);

        content.setTop(hb);

        return content;

    }

    public void outputPreviousPos(TablePosition previousPos){

        System.out.println("previousPos = " + previousPos);

    }

    public void moveToPreviousPos(TablePosition previousPos) {

        //select() in TableView.java expects TableColumn<S, ?>
        //getTableColumn() in TablePosition.java returns TableColumn<S,T>
        //getColumns() in TableView.java returns an ObservableList of type TableColumn(S, ?)

        //Is that why the following line generates  "unchecked method invocation" and "unchecked conversion" errors
        //table.getSelectionModel().select
        //      (previousPos.getRow(), previousPos.getTableColumn());
        //but the following line compiles clean?
        table.getSelectionModel().select
                (previousPos.getRow(), table.getColumns().get(previousPos.getColumn()));

    }

    public class TestModel {

        private StringProperty text;

        public TestModel() {
            this("");
        }

        public TestModel(
            String text
        ) {
            this.text = new SimpleStringProperty(text);
        }

        public String getText() {
            return text.get();
        }

        public void setText(String text) {
            this.text.set(text);
        }

        public StringProperty textProperty() {
            return text;
        }

    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setTitle("Test");
        stage.setWidth(500);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

推荐答案

首先,我想说这是 TableView.getFocusModel().getFocusedCell()(或 focusedCellProperty())使用原始的 TablePosition 类型(原始的 TablePosition 只能转换为 TablePositon<?,?> 而不会产生警告).更合适的版本可能是 TablePosition< S,?> .

First of all, I would say that it was a design flaw that TableView.getFocusModel().getFocusedCell() (or focusedCellProperty()) uses the raw TablePosition type (raw TablePosition can only be cast to TablePositon<?, ?> without generating warning). The more suitable version could have been TablePosition<S, ?>.

由于 TablePosition 表示 TableView 中任何地方的特定单元格,因此对于 TableView.getFocusModel().focusedCellProperty():

Since TablePosition represents a particular cell anywhere in the TableView, then for TableView.getFocusModel().focusedCellProperty():

  1. S 的类型对于 TableView< S> 是固定的(即类型是已知的).
  2. T 的类型是指特定 TableColumn 的类型,它可以根据聚焦的单元格而变化.您无法在编译时确定类型,因为您不知道将选择哪个 TableColumn< S,T> .
  1. The type of S is fixed for TableView<S> (i.e. the type is known).
  2. The type of T refers to the type of a particular TableColumn, which can change depending on which cell has been focused. You cannot determine the type at compile time because you have no idea which TableColumn<S, T> would be selected.

现在到第二点.

这是因为 TableColumn< S,?> 中的?是通配符.由于 TableViewFocusModel< S> 不具有 T 类型,并且它不能基于固定列进行操作,因此必须使用?在这里(请参阅我解释的第一点).

This is because ? in TableColumn<S, ?> is a wildcard. Since TableViewFocusModel<S> does not have the type T and that it does not operate based on a fixed column, so it has to use ? here (see the first point that I explained).

另一方面, TableView.getSelectionModel().select()期望 row int TableColumn<S,?> 列.由于您具有 TablePosition<?,因此?>previousPos ,因此 previousPos 也会返回 TableColumn<?,?> . TableColumn< S,? TableColumn<?,?> 非常不同-您可以将 TableColumn 与另一个 TableView ,如果允许 TableColumn<?,?> .

On the other hand, TableView.getSelectionModel().select() expects an int for row and a TableColumn<S, ?> for column. Since you had TablePosition<?, ?> previousPos, so previousPos would return a TableColumn<?, ?> as well. TableColumn<S, ? and TableColumn<?, ?> are very different - you could use the TableColumn from another TableView if TableColumn<?, ?> is allowed.

最后,如果 TableView.getFocusModel().getFocusedCell()的API是固定的,那么在使用 select()时就不会有问题.在此之前,您可以手动将其强制转换为 TablePosition< TestModel,?> ,或者像您一样使用 TableView.getColumns().get(index)

Finally, if the API for TableView.getFocusModel().getFocusedCell() is fixed, then there would not be a problem when you use select(). Until then, you could manually cast it to TablePosition<TestModel, ?> with a suppression, or use TableView.getColumns().get(index) like what you did.

这篇关于当使用TableColumn&lt; S,T&amp; gt;时,为什么编译器会生成未经检查的警告而不是TableColumn&lt; S,&lt;&gt;在JavaFX8 TableView中选择一个单元格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-23 03:00