单击并按住鼠标按钮,JavaFX Spinner更改速度很慢

swi*_*son 5 javafx javafx-8

单击并按住向上/向下箭头按钮时,Spinner更新的速度很慢.有没有办法提高变化速度?

当我单击,单击,单击鼠标时,微调器值会随着我单击而变化.如果我在每次按键时使用键盘上的向上/向下箭头或者按住向上/向下箭头键,它也会快速变化.当我点击并按住箭头按钮时,我希望值快速改变.

有人知道这样做的方法吗?

fab*_*ian 5

SpinnerBehavior对的SpinnerSkin触发每750毫秒更新。不幸的是,如果不使用反射来访问private成员,就无法简单地设置/修改这种行为。因此,做到这一点而无需反思的唯一方法是使用事件过滤器以更快的速度触发更新:

private static final PseudoClass PRESSED = PseudoClass.getPseudoClass("pressed");

@Override
public void start(Stage primaryStage) {
    Spinner<Integer> spinner = new Spinner(Integer.MIN_VALUE, Integer.MAX_VALUE, 0);

    class IncrementHandler implements EventHandler<MouseEvent> {

        private Spinner spinner;
        private boolean increment;
        private long startTimestamp;

        private static final long DELAY = 1000l * 1000L * 750L; // 0.75 sec
        private Node button;

        private final AnimationTimer timer = new AnimationTimer() {

            @Override
            public void handle(long now) {
                if (now - startTimestamp >= DELAY) {
                    // trigger updates every frame once the initial delay is over
                    if (increment) {
                        spinner.increment();
                    } else {
                        spinner.decrement();
                    }
                }
            }
        };

        @Override
        public void handle(MouseEvent event) {
            if (event.getButton() == MouseButton.PRIMARY) {
                Spinner source = (Spinner) event.getSource();
                Node node = event.getPickResult().getIntersectedNode();

                Boolean increment = null;
                // find which kind of button was pressed and if one was pressed
                while (increment == null && node != source) {
                    if (node.getStyleClass().contains("increment-arrow-button")) {
                        increment = Boolean.TRUE;
                    } else if (node.getStyleClass().contains("decrement-arrow-button")) {
                        increment = Boolean.FALSE;
                    } else {
                        node = node.getParent();
                    }
                }
                if (increment != null) {
                    event.consume();
                    source.requestFocus();
                    spinner = source;
                    this.increment = increment;

                    // timestamp to calculate the delay
                    startTimestamp = System.nanoTime();

                    button = node;

                    // update for css styling
                    node.pseudoClassStateChanged(PRESSED, true);

                    // first value update
                    timer.handle(startTimestamp + DELAY);

                    // trigger timer for more updates later
                    timer.start();
                }
            }
        }

        public void stop() {
            timer.stop();
            button.pseudoClassStateChanged(PRESSED, false);
            button = null;
            spinner = null;
        }
    }

    IncrementHandler handler = new IncrementHandler();
    spinner.addEventFilter(MouseEvent.MOUSE_PRESSED, handler);
    spinner.addEventFilter(MouseEvent.MOUSE_RELEASED, evt -> {
        if (evt.getButton() == MouseButton.PRIMARY) {
            handler.stop();
        }
    });

    Scene scene = new Scene(spinner);

    primaryStage.setScene(scene);
    primaryStage.show();
}       
Run Code Online (Sandbox Code Playgroud)


Nig*_*y42 2

我稍微修改了 fabian 的答案,以降低按住鼠标时旋转器的速度:

private int currentFrame = 0;
private int previousFrame = 0;        

@Override
public void handle(long now)
{
    if (now - startTimestamp >= initialDelay)
        {
        // Single or holded mouse click
        if (currentFrame == previousFrame || currentFrame % 10 == 0)
        {
            if (increment)
            {
                spinner.increment();
            }
            else
            {
                spinner.decrement();
            }
        }
    }

    ++currentFrame;
}
Run Code Online (Sandbox Code Playgroud)

停止计时器后,我们再次调整 previousFrame:

public void stop()
{
    previousFrame = currentFrame;

    [...]
}
Run Code Online (Sandbox Code Playgroud)