JavaFX 11 Замена для column.impl_setWidth ()? - PullRequest
0 голосов
/ 12 ноября 2018

Я написал собственную политику изменения ширины TableColumn. Вы можете увидеть его код под Java 8 / JavaFX 8 здесь, на github . Как вы можете видеть, в методе distributeSpaceRatio() и других местах от TableColumn.impl_setWidth() зависит установка желаемой величины ширины столбцов после выполнения наших вычислений.

Я переносу свой проект на Java 11 / JavaFX 11, и метод impl_setWidth() был удален из общего доступа.

Есть ли другой способ сообщить столбцу таблицы, чтобы установить ее ширину? Я открыт для любого решения, если оно надежно и задает (или близко) к запрошенному значению.

Вот две идеи, которые я до сих пор пробовал, но они не сработали:


Попытка 1:

Это дает NoMethodFoundException:

private void setColumnWidth ( TableColumn column, double targetWidth ) {

    try {
        Method method = column.getClass().getDeclaredMethod( "setWidth" );
        method.setAccessible( true );
        Object r = method.invoke( targetWidth );
    } catch ( Exception e ) {
        e.printStackTrace();
    }
}

Попытка 2:

Этот не имеет никакого эффекта:

private void setColumnWidth ( TableColumn column, double targetWidth ) {

    double oldMax = column.getMaxWidth();
    double oldMin = column.getMinWidth();
    double oldPref = column.getPrefWidth();

    column.setMaxWidth( targetWidth );
    column.setMinWidth( targetWidth );
    column.setPrefWidth( targetWidth );

    column.getTableView().refresh();

    column.setPrefWidth( oldPref );
    column.setMinWidth( oldMin );
    column.setMaxWidth( oldMax );
}

Попытка 3:

Глядя на исходный код TableView.UNCONSTRAINED_RESIZE_POLICY для JavaFX, кажется, что вызванный метод в конечном итоге TableColumnBase.doSetWidth(), но здесь он также не работает:

private void setColumnWidth ( TableColumn column, double targetWidth ) {

    try {
        Method method = column.getClass().getDeclaredMethod( "doSetWidth" );
        method.setAccessible( true );
        Object r = method.invoke( targetWidth );
    } catch ( Exception e ) {
        e.printStackTrace();
    }
}

Попытка 4:

Я также попытался использовать решение, предоставленное в этом ответе , для выполнения частного метода и получил то же исключение - "Не найдено методов с именами doSetWidth и params [класс java.lang.Double ]».


Попытка 5:

Я думал, что этот будет работать, но не такая удача. Это бросило "java.lang.NoSuchFieldException: ширина". Однако, когда я перехожу к исходному коду TableColumnBase, я ясно вижу в строке 412 приватное поле с именем width. Не уверен, почему это не удается.

private void setColumnWidth ( TableColumnBase column, double targetWidth ) {
    try {
        Field widthField = column.getClass().getDeclaredField( "width" );
        widthField.setAccessible( true );
        ReadOnlyDoubleWrapper width = (ReadOnlyDoubleWrapper)widthField.get( column );
        width.set( targetWidth );
    } catch ( Exception e ) {
        e.printStackTrace();
    }
}

Попытка 6:

Это сблизило нас, но все равно не удалось:

private void setColumnWidth ( TableColumnBase column, double targetWidth ) {
    try {
        Field widthField = column.getClass().getSuperclass().getDeclaredField( "width" );
        widthField.setAccessible( true );
        ReadOnlyDoubleWrapper width = (ReadOnlyDoubleWrapper)widthField.get( column );
        width.set( targetWidth );
    } catch ( Exception e ) {
        e.printStackTrace();
    }
}

java.lang.reflect.InaccessibleObjectException: Невозможно сделать поле приватным модуль @ 649dcffc


Попытка 7:

private void setColumnWidth ( TableColumn column, double targetWidth ) {
    try {
        Method method = column.getClass().getSuperclass().getDeclaredMethod( "setWidth", double.class );
        method.setAccessible( true );
        method.invoke ( targetWidth );
        //ReadOnlyDoubleWrapper width = (ReadOnlyDoubleWrapper)widthField.get( column );
        //width.set( targetWidth );
    } catch ( Exception e ) {
        e.printStackTrace();
    }
}

java.lang.reflect.InaccessibleObjectException: Невозможно сделать void javafx.scene.control.TableColumnBase.setWidth (double) доступным: модуль javafx.controls не «открывает javafx.scene.control» для неназванного модуля @ 5063f647

1 Ответ

0 голосов
/ 12 ноября 2018

На основании тестирования и помощи других, я нашел это решение:

private void setColumnWidth ( TableColumn column, double targetWidth ) {
    try {
        Method method = TableColumnBase.class.getDeclaredMethod( "doSetWidth", double.class );
        method.setAccessible( true );
        method.invoke( column, targetWidth );
    } catch ( NoSuchMethodException | InvocationTargetException | IllegalAccessException e ) {
        e.printStackTrace();
    }
}

Кроме того, JVM должна вызываться со следующими аргументами:

--add-opens javafx.controls/javafx.scene.control=ALL-UNNAMED
...