切换垂直 JScrollBar min/max 位置

Switch vertical JScrollBar min/max location

我有一个 vertical JScrollBar,当滚动条值为在模型 最小值.

我想要相反的行为:当值处于最小值时,拇指将位于 底部

我试过 setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT) 它适用于 水平滚动条 但不适用于垂直滚动条...

如何让它按预期工作(如果可能,不创建完整的 ScrollBarUI)? 这是预期的行为吗(水平和垂直滚动条之间的一种 "UI inconsistency"*,或者缺少 ComponentOrientation.BOTTOM_TO_TOP 常量)?

这里有一些 SSCE 可以说明问题:

public static void main(String[] args) throws Exception {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    int orient = JScrollBar.VERTICAL; // <<--- Change to HORIZONTAL
    JScrollBar sb = new JScrollBar(orient, 0, 100, 0, 1000);
    sb.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); // <<--- Works only for HORIZONTAL
    sb.addAdjustmentListener(new AdjustmentListener() {
        @Override public void adjustmentValueChanged(AdjustmentEvent e) {
            System.out.println(e.getValue());
        }
    });
    f.add(sb);
    if (orient == JScrollBar.HORIZONTAL)
        f.setBounds(100, 100, 500, 100);
    else
        f.setBounds(100, 100, 100, 500);
    f.setVisible(true);
}

*: "inconsistency" 因为如果它在水平方向上反转拇指,我希望在垂直方向上也能反转拇指...

编辑:滚动条用于控制地图中的滚动,可以将其配置为原点在屏幕的顶部或底部,向下或向上,或向左或-向右,向右或向左(它必须匹配物理设置,因此是可配置的)。处理左或右设置只是将滚动条设置为水平,从右到左的方向,但同样不适用于垂直。

我还检查了 BasicScrollBarUI 的来源,当滚动条为 HORIZONTAL 时,它确实只处理 getComponentOrientation().isLeftToRight() 。所以这确实是预期的行为(只是不是 I 预期的...)。

我最终将 JScrollBar 子类化为 getAdjustedValue() 进行翻译。这个想法是 "reverse" 最小和最大,所以 [min;max] 变成 [-max;-min]。然后我们在调整模型值时必须考虑范围,因为拇指底部(value + extent)是我们想要的值:

public static class MySB extends JScrollBar {
    private boolean inv;
    public MySB(int orient, int value, int extent, int min, int max, boolean inv) {
        super(orient, inv ? -value-extent : value, extent, inv ? -max : min, inv ? -min : max);
        this.inv = inv;
    }
    public int getAdjustedValue() {
        int v = super.getValue();
        if (inv)
            v = -(v + model.getExtent());
        return v;
    }
}

然后修改上面的SSCE,在AdjustmentListener中加入sb.getAdjustedValue()

...
MySB sb = new MySB(orient, 0, 100, 0, 1000, true);
sb.addAdjustmentListener(new AdjustmentListener() {
    @Override
    public void adjustmentValueChanged(AdjustmentEvent e) {
        System.out.println(e.getValue()+", "+((MySB)e.getAdjustable()).getMyValue());
    }
});
...

-100, 0
-200, 100
-200, 100
-200, 100
-300, 200
-300, 200

我们看到了原始值和更正后的值。我最初开始对模型进行子类化并覆盖 getValue() 但它弄乱了页面 up/down 和箭头行为。