数字/轴:如何在布局期间强制立即更新内部状态?

时间:2015-12-07 17:01:17

标签: java slider javafx-8 axis

question about Slider和一个小错误触发,我试图实现一个利用轴服务的SliderSkin,特别是它在像素和值之间的转换方法。工作正常,但NumberAxis将其转换偏移和比例因子保持为仅在布局过程中更新的内部字段。

如果我想在布局脉冲期间使用转换来更新另一个协作者,那么会出现问题:如果是滑块,那就是拇指。

下面是一个演示问题的小例子:只是一个NumberAxis和一个值的CheckBox。启动时,框放在中间的值。为获得最大效果,请最大化窗口并注意框位置未更改 - 现在位于轴的起点附近。实际上,在调整窗口大小但是不那么明显时也是如此 - 请参阅差异的打印输出。

使其有效的选项

  • 延迟拇指定位,直到下一个布局脉冲(感觉笨拙)
  • 强制轴立即更新

寻找后者的方法(除了反射调用轴'layoutChildren之外找不到任何东西)。

示例:

public class AxisInvalidate extends Application {

    public static class AxisInRegion extends Region {
        NumberAxis axis;
        Control thumb;
        IntegerProperty value = new SimpleIntegerProperty(50);

        private double thumbWidth;
        private double thumbHeight;

        public AxisInRegion() {
            axis = new NumberAxis(0, 100, 25);
            thumb = new CheckBox();
            getChildren().addAll(axis, thumb);
        }

        @Override
        protected void layoutChildren() {
            thumbWidth = snapSize(thumb.prefWidth(-1));
            thumbHeight = snapSize(thumb.prefHeight(-1));
            thumb.resize(thumbWidth, thumbHeight);

            double axisHeight = axis.prefHeight(-1);
            axis.resizeRelocate(0, getHeight() /4, getWidth(), axisHeight);
            // this marks the layout as dirty but doesn't immediately update internals
            // doesn't make a difference, shouldn't be needed anyway
            //axis.requestAxisLayout();

            double pixelOnAxis = axis.getDisplayPosition(value.getValue());
            Platform.runLater(() -> {
                LOG.info("diff " + (pixelOnAxis - axis.getDisplayPosition(value.getValue())));
            });
            // moving this line into the runlater "solves" the problem  
            thumb.relocate(pixelOnAxis, getHeight() /4);

        }

    }

    private Parent getContent() {
        AxisInRegion region = new AxisInRegion();
        BorderPane content = new BorderPane(region);
        return content;
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(new Scene(getContent(), 500, 200));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger.getLogger(AxisInvalidate.class
            .getName());
}

实际上,I think it's a bug:值/像素转换是Axis的公共服务 - 应始终有效。

2 个答案:

答案 0 :(得分:1)

不确定它是否对您的初始问题有帮助,但只是手动执行计算。另一个加号 - 请求布局变得不必要,可以删除。

  double range = axis.getUpperBound()-axis.getLowerBound();
  double pixelOnAxis = axis.getWidth()*(value.get()-axis.getLowerBound())/range;

答案 1 :(得分:0)

刚从bug report开始工作:我们需要在更改大小/位置之后调用axis.layout(),然后再查询转换方法,例如:

axis.resizeRelocate(0, getHeight() /4, getWidth(), axisHeight);
// doesn't make a difference, shouldn't be needed anyway
//axis.requestAxisLayout();
// working hack from bug report:
axis.layout();
double pixelOnAxis = axis.getDisplayPosition(value.getValue());
thumb.relocate(pixelOnAxis, getHeight() /4);