Zoom JavaFX: scrollevent scrolls when the content size exceeds the scrollpane viewport

I have an application that needs to enlarge scrollpane, but I still face two challenges In order to copy the problem, I wrote a small application zoomapp, and you will find the following code Its limited functionality allows you to zoom in and out on some arbitrary shapes (using the CTRL mouse wheel) Scrollbars should be disabled when zoomed content grows outside the window's boundaries

Challenge 1 When the scroll bar shows the result of innergroup increasing in size, the scrollevent no longer reaches my zoomhandler Instead, we start scrolling down the window until it reaches the bottom and works properly when zoomed again I thought maybe

scrollPane.setPannable(false);

Will make a difference, but not How to avoid this unnecessary behavior?

Challenge 2 How to put innergroup in the center of scrollpane without drawing a pixel to the desired triangle to square in the upper left corner of the internal group?

According to Javadoc for scrollpane, "if an application wants scrolling to be node based visual boundaries (for zooming content, etc.), it needs to wrap the scrolling nodes in groups" This is why I have an innergroup and an outergroup in scrollpane

Any suggestions that lead me to solve this problem are highly appreciated by JavaFX novices

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/**
 * Demo of a challenge I have with zooming inside a {@code ScrollPane}.
 * <br>
 * I am running JavaFx 2.2 on a Mac. {@code java -version} yields:
 * <pre>
 * java version "1.7.0_09"
 * Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
 * Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02,mixed mode)
 * </pre>
 * 6 rectangles are drawn,and can be zoomed in and out using either
 * <pre>
 * Ctrl + Mouse Wheel
 * or Ctrl + 2 fingers on the pad.
 * </pre>
 * It reproduces a problem I experience inside an application I am writing.
 * If you magnify to {@link #MAX_SCALE},an interesting problem occurs when you try to zoom back to {@link #MIN_SCALE}. In the beginning
 * you will see that the {@code scrollPane} scrolls and consumes the {@code ScrollEvent} until we have scrolled to the bottom of the window.
 * Once the bottom of the window is reached,it behaves as expected (or at least as I was expecting).
 *
 * @author Skjalg Bjørndal
 * @since 2012.11.05
 */
public class ZoomApp extends Application {

    private static final int WINDOW_WIDTH = 800;
    private static final int WINDOW_HEIGHT = 600;

    private static final double MAX_SCALE = 2.5d;
    private static final double MIN_SCALE = .5d;

    private class ZoomHandler implements EventHandler<ScrollEvent> {

        private Node nodeToZoom;

        private ZoomHandler(Node nodeToZoom) {
            this.nodeToZoom = nodeToZoom;
        }

        @Override
        public void handle(ScrollEvent scrollEvent) {
            if (scrollEvent.isControlDown()) {
                final double scale = calculateScale(scrollEvent);
                nodeToZoom.setScaleX(scale);
                nodeToZoom.setScaleY(scale);
                scrollEvent.consume();
            }
        }

        private double calculateScale(ScrollEvent scrollEvent) {
            double scale = nodeToZoom.getScaleX() + scrollEvent.getDeltaY() / 100;

            if (scale <= MIN_SCALE) {
                scale = MIN_SCALE;
            } else if (scale >= MAX_SCALE) {
                scale = MAX_SCALE;
            }
            return scale;
        }
    }

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

    @Override
    public void start(Stage stage) throws Exception {

        final Group innerGroup = createSixRectangles();
        final Group outerGroup = new Group(innerGroup);

        final ScrollPane scrollPane = new ScrollPane();
        scrollPane.setContent(outerGroup);
        scrollPane.setOnScroll(new ZoomHandler(innerGroup));

        StackPane stackPane = new StackPane();
        stackPane.getChildren().add(scrollPane);

        Scene scene = SceneBuilder.create()
                .width(WINDOW_WIDTH)
                .height(WINDOW_HEIGHT)
                .root(stackPane)
                .build();

        stage.setScene(scene);
        stage.show();
    }

    private Group createSixRectangles() {
        return new Group(
                createRectangle(0,0),createRectangle(110,createRectangle(220,createRectangle(0,110),220),220)
        );
    }

    private Rectangle createRectangle(int x,int y) {
        Rectangle rectangle = new Rectangle(x,y,100,100);
        rectangle.setstroke(Color.ORANGERED);
        rectangle.setFill(Color.ORANGE);
        rectangle.setstrokeWidth(3d);
        return rectangle;
    }
}

Solution

OK, so I finally found a solution to my problem

Just replace it with a line

scrollPane.setOnScroll(new ZoomHandler(innerGroup));

with

scrollPane.addEventFilter(ScrollEvent.ANY,new ZoomHandler(innerGroup));

It is now working as expected No need for mysterious rectangles or other hackers

So why is the next question? According to this excellent article on processing events,

and

I think there is no difference

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>