Как получить TableColumn типаиз модели фокуса TableView в JavaFX8 и все еще получить чистую компиляцию? - PullRequest
0 голосов
/ 10 октября 2018

Другой относительный вопрос новичка в Java.

Я очищаю свой код и перехожу к последним двум проблемам с компилятором.Оба относятся к необходимости получения TableColumn типа <S, T> от звонка на tableView.getFocusModel().getFocusedCell().Я получаю предупреждения компилятора и пока не смог их разрешить.

Я думаю, что предупреждения проистекают из использования фокус-моделью TableView необработанного типа TablePosition и, если я 'Правильно понимая последствия, это означает, что любой TableColumn на основе TablePosition, возвращенный из вызова к tableView.getFocusModel().getFocusedCell() , имеет , который должен быть объявлен как raw для того, чтобыкод для чистой компиляции.

IE.если я сделаю это:

TablePosition pos = tableView.getFocusModel().getFocusedCell();

, тогда я получу чистую компиляцию только тогда, когда я сделаю это:

TableColumn col = pos.getTableColumn();

TablePosition.java в документации Javaговорит, что pos.getTableColumn() возвращает TableColumn<S,T>, и я думаю, что это невозможно, если фокусная модель возвращает необработанный TablePosition тип.Я понимаю, что.

Но, , если мне нужно объявить TableColumn как raw, как я могу "преобразовать" его в тип <S, T> (или обойти дженерики?) Так, чтобыЯ получаю TableColumn<S, T> и все равно получаю чистую компиляцию ?Как только я это узнаю, я надеюсь, что смогу исправить последние две проблемы с компилятором.

Я экспериментировал с принятым ответом в Как обойти ограничения универсальных символов подстановки Java и пока это работает,подавление ошибок компилятора не то, что я хочу сделать.Я также попытался использовать модель выбора TableView, а не модель фокуса, но кажется, что table.getSelectionModel().getSelectedCells().get(0) также возвращает необработанный TablePosition.Использование фокусной модели raw TablePosition было объяснено пользователем Jai в ответ на предыдущий вопрос, который я задал Почему компилятор генерирует непроверенные предупреждения при использовании TableColumnа не TableColumnвыбрать ячейку в JavaFX8 TableView? ).

Если поможет, вот MVCE, с которым я играл, чтобы попытаться решить последние две проблемы компилятора.Оба связаны с необходимостью получения TableColumn типа <S, T> в каждом из методов getFocussedColumn() и getGraphic().Я оставил свои комментарии, чтобы вы могли видеть, что я пробовал.Кроме того, для того, чтобы воспроизвести проблемы, MVCE пришлось использовать настраиваемую ячейку флажка, которую использует мое приложение.Я сократил его настолько, насколько смог, чтобы сохранить его как можно более "M".

Я использую JavaFX8 (JDK1.8.0_181), NetBeans 8.2 и Scene Builder 8.3.

Я компилирую с "-Xlint: unchecked".

package test28;

import java.util.function.BiConsumer;
import java.util.function.Function;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Test28 extends Application {

    static TableView<TestModel> table = new TableView<>();
    ToggleGroup tgRadios = new ToggleGroup();

    private Parent createContent() {

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

        olTestModel.add(new TestModel(false));
        olTestModel.add(new TestModel(true));
        olTestModel.add(new TestModel(false));

        table.setItems(olTestModel);
        Platform.runLater(() -> table.getSelectionModel().selectFirst());

        //Column with a custom cell that renders as a CheckBox
        TableColumn<TestModel, Boolean> colCheckbox = createCheckBoxColumn("checkbox", TestModel::checkboxProperty, TestModel::setCheckbox);

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

        Button btnGetFocussedCol = new Button("get focussed col");
        btnGetFocussedCol.setOnAction(event -> {
            TableColumn<TestModel, Boolean> col = getFocussedColumn();
            System.out.println("col = " + col);
        });

        Button btnGetGraphic = new Button("get graphic");
        btnGetGraphic.setOnAction(event -> {
            Node node = getGraphic();
            System.out.println("node = " + node);
        });

        BorderPane content = new BorderPane(table);
        HBox hb = new HBox();
        hb.setPadding(new Insets(10,10,10,10));
        hb.setSpacing(20.0);
        hb.getChildren().addAll(btnGetFocussedCol, btnGetGraphic);

        content.setTop(hb);

        return content;

    }

    //*************************************************************************************
    //First of two remaining compiler issues to resolve

    private static <S, T> TableColumn<S, T> getFocussedColumn() {

        //getFocusedCell() returns a RAW TablePosition
        TablePosition pos = table.getFocusModel().getFocusedCell();

        //pos.getTableColumn() should be returning TableColumn<S,T>, however, pos is a RAW type
        //so I guess that's why I'm getting an unchecked conversion warning on the following line
        //TableColumn<S, T> col = pos.getTableColumn();

        //Casting it generates an unchecked cast warning
        //TableColumn<S, T> col = (TableColumn<S, T>) pos.getTableColumn();

        //Using a RAW TableColumn type fixes the warnings on the TableColumn declaration
        //but generates an unchecked conversion warning on the "return col" line
        TableColumn col = pos.getTableColumn();

        //table.getColumns() returns ObservableList<TableColumn<S,?>>, so I cannot use the following
        //TableColumn<S, T> col = table.getColumns().get(pos.getColumn());

        //getFocusedCell().getTableColumn() returns TableColumn<S,?>, so I cannot do the following
        //return table.getFocusModel().getFocusedCell().getTableColumn();

        //unchecked conversion warning generated on this line when TableColumn is raw
        //==> HOW CAN I "CONVERT" A RAW TABLECOLUMN TO TABLECOLUMN<S, T>?
        return col;

    }

    //*************************************************************************************
    //Second of two remaining compiler issues to resolve

    public <S, T> Node getGraphic() {

        TablePosition pos = table.getFocusModel().getFocusedCell();

        //Declaring TableColumn as a raw type generates an "unchecked call to call(P) as a member of the raw type Callback"
        //warning on the TableCell declaration below
        TableColumn col = pos.getTableColumn();

        //getCellFactory().call() expects CellDataFeatures<S,T> and returns ObservableValue<T>
        //unchecked call to call(P) warning generated on this line when TableColumn is raw
        //==> HOW CAN I "CONVERT" A RAW TABLECOLUMN TO TABLECOLUMN<S, T>?
        TableCell cell = (TableCell) col.getCellFactory().call(col);

        Node cellGraphic = cell.getGraphic();
        return cellGraphic;

    }

    //*************************************************************************************
    //Create a custom checkbox

    public <S> TableColumn<S, Boolean> createCheckBoxColumn(String title, 
            Function<S, BooleanProperty> methodGetCheckBoxFieldProperty, 
            BiConsumer<? super S, ? super Boolean> methodSetCheckBoxField) {

        TableColumn<S, Boolean> col = new TableColumn<>(title);

        col.setCellValueFactory(cellData -> methodGetCheckBoxFieldProperty.apply(cellData.getValue()));

        col.setCellFactory(column -> CheckBoxCell.createCheckBoxCell());

        col.setOnEditCommit(event -> {
            Boolean masterCode = event.getNewValue();
            S dataModel = event.getRowValue();
            methodSetCheckBoxField.accept(dataModel, masterCode);
        });

        return col;

    }

    //*************************************************************************************
    //The custom CheckBoxCell class

    public static class CheckBoxCell<S, T> extends TableCell<S, T> {

        private final CheckBox checkBox = new CheckBox();

        public CheckBoxCell() {

            setGraphic(checkBox);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

        }

        public static <S> CheckBoxCell<S, Boolean> createCheckBoxCell() {
            return new CheckBoxCell<S, Boolean>();
        }

        @Override
        protected void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
            } else {
                setText( ((Boolean) item).toString());
                checkBox.setSelected( (Boolean) item);
                setGraphic(checkBox);
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            }
        }

    }    

    //*************************************************************************************

    public class TestModel {

        private BooleanProperty checkbox;

        public TestModel() {
            this(false);
        }

        public TestModel(
            boolean checkbox
        ) {
            this.checkbox = new SimpleBooleanProperty(checkbox);
        }

        public boolean getCheckbox() {
            return checkbox.get();
        }

        public void setCheckbox(boolean checkbox) {
            this.checkbox.set(checkbox);
        }

        public BooleanProperty checkboxProperty() {
            return checkbox;
        }

    }

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

}

1 Ответ

0 голосов
/ 10 октября 2018

Благодаря помощи пользователя Jai ответ заключается в том, что единственный способ получить TableColumn<S, T> от вызова на tableView.getFocusModel().getFocusedCell(); И получить чистую компиляцию - это использовать аннотацию @SuppressWarnings("unchecked").

Этопотому что:

  1. API TableView написан так, чтобы возвращать необработанный тип TablePosition из getFocusedCell().
  2. Там не существуетпреобразовать необработанный тип в <S, T> (или любой другой) тип.Это очень разные вещи.

Итак, проблемы с компилятором, выделенные в MVCE в моем вопросе, были решены так:

@SuppressWarnings("unchecked") 
private static <S, T> TableColumn<S, T> getFocussedColumnx() {
    TablePosition<S, T> pos = (TablePosition<S, T>) table.getFocusModel().getFocusedCell();
    TableColumn<S, T> col = (TableColumn<S, T>) pos.getTableColumn();
    return col;
}

и это:

@SuppressWarnings("unchecked")
public <S, T> Node getGraphic() {
    TablePosition<S, T> pos = (TablePosition<S, T>) table.getFocusModel().getFocusedCell();
    TableColumn<S, T> col = (TableColumn<S, T>) pos.getTableColumn();
    TableCell<S, T> cell = (TableCell<S, T>) col.getCellFactory().call(col);
    Node cellGraphic = cell.getGraphic();
    return cellGraphic;
}

Спасибо, Джай, за то, что указал мне правильное направление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...