用JavaFX 11替换column.impl_setWidth()吗?

时间:2018-11-12 03:04:46

标签: java javafx java-11 javafx-11

我写了一个自定义的TableColumn宽度调整大小策略。您可以在Java下查看其代码 8 / JavaFX 8 here on 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:

看一下JavaFX的TableView.UNCONSTRAINED_RESIZE_POLICY的来源,看来所调用的方法最终是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:

我还尝试使用this answer中提供的解决方案来执行私有方法,并且遇到了相同的例外-“找不到名称为doSetWidth和params [class 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:无法将字段设置为私有javafx.beans.property.ReadOnlyDoubleWrapper javafx.scene.control.TableColumnBase.width可以访问:模块javafx.controls不会“打开javafx.scene.control”为未命名模块@ 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 :(得分:2)

基于测试和其他人的帮助,我找到了以下解决方案:

class array<int> a(5);
a[0] = 8;
a[1] = 6;
a[2] = 7;
a[3] = 1;
a[4] = 3;

std::cout << "attempting sort" << std::endl;
a.sort(wrap_insertion_sort_recursive<int>, custom_comparator<int>);

此外,需要使用以下参数来调用JVM:

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