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

问题描述

一个相对的Java新手问题。

A relative Java newbie question.

我正在清理我的代码并遇到两个未经检查的警告( unchecked method invocation 未选中的转换),同时以编程方式选择 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()

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> TableView.java 中的 getColumns()返回类型为 ObservableList > TableColumn(S,?)。

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 中的特定单元格 where ,然后表示 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.

现在到第二点。

这是因为 in 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()期望 int TableColumn< S,?> for列。由于你有 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&gt;时会生成未经检查的警告而不是TableColumn&lt; S,?&gt;在JavaFX8 TableView中选择一个单元格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 20:56