Java 编号/轴:如何在布局期间强制立即更新内部状态?
受到一个小错误和一个小错误的触发,我尝试实现一个利用axis服务的SliderSkin,特别是它在像素和值之间的转换方法。工作正常,只是NumberAxis将其转换偏移量和比例因子保持为仅在布局过程中更新的内部字段 如果我想在布局脉冲期间使用转换来更新另一个协作者,这就带来了一个问题:在滑块的情况下,它将是拇指 下面是一个小例子来演示这个问题:只需一个NumberAxis和某个值的复选框。启动时,长方体将放置在中间的值处。为了获得最大效果,请最大化窗口,并注意长方体的位置没有改变-现在位于轴的起点附近。实际上,调整窗口大小时也是如此,但不太明显-请参见差异的打印输出 让它工作的选项Java 编号/轴:如何在布局期间强制立即更新内部状态?,java,slider,javafx-8,axis,Java,Slider,Javafx 8,Axis,受到一个小错误和一个小错误的触发,我尝试实现一个利用axis服务的SliderSkin,特别是它在像素和值之间的转换方法。工作正常,只是NumberAxis将其转换偏移量和比例因子保持为仅在布局过程中更新的内部字段 如果我想在布局脉冲期间使用转换来更新另一个协作者,这就带来了一个问题:在滑块的情况下,它将是拇指 下面是一个小例子来演示这个问题:只需一个NumberAxis和某个值的复选框。启动时,长方体将放置在中间的值处。为了获得最大效果,请最大化窗口,并注意长方体的位置没有改变-现在位于轴的起
- 延迟拇指定位,直到下一个布局脉冲(感觉笨拙)
- 强制轴立即更新
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());
}
实际上,值/像素转换是Axis的一项公共服务,应该一直有效 不确定这是否有助于您的首次发行,只需手动计算即可。另一个plus-request布局变得不必要,可以删除
double range = axis.getUpperBound()-axis.getLowerBound();
double pixelOnAxis = axis.getWidth()*(value.get()-axis.getLowerBound())/range;
刚刚从中得到了一个有用的技巧:我们需要在更改大小/位置之后,在查询转换方法之前调用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);
当然,另一个可行的选择,谢谢:-)更愿意避免手动操作。事实上,我认为“加号”(在这种情况下没有任何区别,只是因为核心代码经常添加它而添加)是一个bug:公共服务必须始终正确提供;-)@GunnarBernstein hach,忘记接受我自己的——多年来:)