为什么编译器在使用 TableColumn<S, T> 而不是 TableColumn<S, ?> 到 select JavaFX8 TableView 中的单元格时生成未经检查的警告?
Why does the compiler generate unchecked warnings when using TableColumn<S, T> rather than TableColumn<S, ?> to select a cell in a JavaFX8 TableView?
亲戚Java菜鸟问题
我正在清理我的代码,遇到了两个未经检查的警告(“未经检查的方法调用”和“未经检查的转换”)在以编程方式选择 TableView
中的单元格时。我能够解决这些警告,但不明白是什么原因造成的。
这就是我最初编码 select()
:
的方式
TablePosition<?, ?> previousPos;
//...
table.getSelectionModel().select
(previousPos.getRow(), previousPos.getTableColumn());
我通过将其更改为此解决了警告。
table.getSelectionModel().select
(previousPos.getRow(), table.getColumns().get(previousPos.getColumn()));
我不明白其中的区别,所以我查看了 Java 源代码。如果我解释正确,TableView.java 中的 select()
方法需要 TableColumn<S, ?>
。但是,getTableColumn()
在 TablePosition.java returns TableColumn<S,T>
而 getColumns()
在 TableView.java returns 类型 TableColumn(S, ?)
的 ObservableList
。
我想这就是 table.getColumns().get(...)
编译干净而 previousPos.getTableColumn()
产生错误的原因。
但是,从编译器的角度来看,TableColumn<S, ?>
和 TableColumn<S,T>
之间有什么区别呢?为什么它不能将 T
解析为 ?
.
(这是正确的术语吗?)
如果有帮助,这是我用来尝试找出答案的 MVCE,但答案超出了我目前的 Java 知识范围。 select()
在 moveToPreviousPos()
.
我正在使用 JavaFX8 (JDK1.8.0_181)、NetBeans 8.2 和 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, ?>
.
由于 TablePosition
表示 TableView
中 任意位置 的特定单元格,因此对于 TableView.getFocusModel().focusedCellProperty()
:
S
的类型固定用于 TableView<S>
(即类型已知)。
T
的类型指的是特定 TableColumn
的类型,它可以根据焦点所在的单元格而改变。您无法在编译时确定类型,因为您不知道将选择哪个 TableColumn<S, 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 ?
.
这是因为TableColumn<S, ?>
中的?
是通配符。由于 TableViewFocusModel<S>
没有类型 T
并且它不基于固定列进行操作,所以它必须在这里使用 ?
(见我解释的第一点)。
另一方面,TableView.getSelectionModel().select()
期望 row
的 int
和列的 TableColumn<S, ?>
。因为你有 TablePosition<?, ?> previousPos
,所以 previousPos
也会 return 和 TableColumn<?, ?>
。 TableColumn<S, ?
和 TableColumn<?, ?>
非常不同 - 如果允许 TableColumn<?, ?>
,您可以使用另一个 TableView
的 TableColumn
。
最后,如果TableView.getFocusModel().getFocusedCell()
的API是固定的,那么使用select()
就不会有问题了。在那之前,您可以手动将其强制转换为 TablePosition<TestModel, ?>
,或者像您所做的那样使用 TableView.getColumns().get(index)
。
亲戚Java菜鸟问题
我正在清理我的代码,遇到了两个未经检查的警告(“未经检查的方法调用”和“未经检查的转换”)在以编程方式选择 TableView
中的单元格时。我能够解决这些警告,但不明白是什么原因造成的。
这就是我最初编码 select()
:
TablePosition<?, ?> previousPos;
//...
table.getSelectionModel().select
(previousPos.getRow(), previousPos.getTableColumn());
我通过将其更改为此解决了警告。
table.getSelectionModel().select
(previousPos.getRow(), table.getColumns().get(previousPos.getColumn()));
我不明白其中的区别,所以我查看了 Java 源代码。如果我解释正确,TableView.java 中的 select()
方法需要 TableColumn<S, ?>
。但是,getTableColumn()
在 TablePosition.java returns TableColumn<S,T>
而 getColumns()
在 TableView.java returns 类型 TableColumn(S, ?)
的 ObservableList
。
我想这就是 table.getColumns().get(...)
编译干净而 previousPos.getTableColumn()
产生错误的原因。
但是,从编译器的角度来看,TableColumn<S, ?>
和 TableColumn<S,T>
之间有什么区别呢?为什么它不能将 T
解析为 ?
.
如果有帮助,这是我用来尝试找出答案的 MVCE,但答案超出了我目前的 Java 知识范围。 select()
在 moveToPreviousPos()
.
我正在使用 JavaFX8 (JDK1.8.0_181)、NetBeans 8.2 和 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, ?>
.
由于 TablePosition
表示 TableView
中 任意位置 的特定单元格,因此对于 TableView.getFocusModel().focusedCellProperty()
:
S
的类型固定用于TableView<S>
(即类型已知)。T
的类型指的是特定TableColumn
的类型,它可以根据焦点所在的单元格而改变。您无法在编译时确定类型,因为您不知道将选择哪个TableColumn<S, T>
。
现在进入第二点。
But what is the difference, then, between
TableColumn<S, ?>
andTableColumn<S,T>
from the compiler's point of view? Why doesn't it resolve (is that the correct term?) theT
to?
.
这是因为TableColumn<S, ?>
中的?
是通配符。由于 TableViewFocusModel<S>
没有类型 T
并且它不基于固定列进行操作,所以它必须在这里使用 ?
(见我解释的第一点)。
另一方面,TableView.getSelectionModel().select()
期望 row
的 int
和列的 TableColumn<S, ?>
。因为你有 TablePosition<?, ?> previousPos
,所以 previousPos
也会 return 和 TableColumn<?, ?>
。 TableColumn<S, ?
和 TableColumn<?, ?>
非常不同 - 如果允许 TableColumn<?, ?>
,您可以使用另一个 TableView
的 TableColumn
。
最后,如果TableView.getFocusModel().getFocusedCell()
的API是固定的,那么使用select()
就不会有问题了。在那之前,您可以手动将其强制转换为 TablePosition<TestModel, ?>
,或者像您所做的那样使用 TableView.getColumns().get(index)
。