3

I ask for your help because I have a problem with a ScrollPane in JavaFX.

I added a Group into the scrollPane, added the scrollpane to the Scene and finally put it into a JFXPanel because I use it in a Swing application and it's working well, next I added components into the Group (by components I mean an assembly of Nodes like Rectangles, etc ...). That works well, but when I want to move a component out of the scrollpane layout, the movement of the components is uncontrollable, it starts moving really fast and I don't understand why. It starts troubling just when the border of the component touch the border of the scrollpane layout. I tried to use ScrollBar instead but it seems that the ScrollPane is the most suitable object for this.

There is the code I used to create my view :

public void createView() {
    this.architectureJFXPanel = new JFXPanel();
    this.group = new Group();
    this.scrollPane = new ScrollPane();


    this.scrollPane.setContent(group);
    this.scrollPane.setOnKeyPressed(new KeyPressed());

    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            Scene scene = new Scene(scrollPane, Color.WHITE);
            architectureJFXPanel.setScene(scene);
        }
   });
}

To put the components into the view I use group.getChildren.add() and after that I put the JFXPanel into the swing application.

Here is an example of what I'm trying to do. You can see that on the picture I try to move the component out of the layout:

enter image description here

So if someone already had this kind of problem and could help me I would be really greatful :) Ask me if you need more informations to understand where is the problem.

assylias
  • 321,522
  • 82
  • 660
  • 783
AwaX
  • 448
  • 3
  • 8
  • 19

1 Answers1

1

Here's my work-around for the ScrollPane using ScrollBar.

public void setStyle() {
    // In my program, TextField controls were generate at run-time, so the prefer height is calculated based on number of controls       
    int preHeight = 1000;
    Group root = new Group();

    // This anchor pane contains all control.
    AnchorPane anchorPane = new AnchorPane();
    // TODO: Add control into this anchor pane
    // anchorPane.getChildren().addAll();

    final ScrollBar sc = new ScrollBar();
    root.getChildren().addAll(anchorPane, sc);

    // Set default size for scene to 800 x 600
    int sceneW = 800;
    int sceneH = 600;
    final Scene scene = new Scene(root, sceneW, sceneH);

    // Setting for the scroll bar
    sc.setLayoutX(scene.getWidth()- sc.getWidth()/2 - 1);
    sc.setMin(0);
    sc.setOrientation(Orientation.VERTICAL);
    sc.setPrefHeight(sceneH);
    sc.setMax(preHeight - sceneH);

    // In case prefer height is smaller than scene height then hide the scroll bar
    if(preHeight < sceneH) {
        sc.setVisible(false);
    }

    scene.setRoot(root);

    // Change the scroll bar and the anchor pane when user change scene's width
    scene.widthProperty().addListener(new ChangeListener<Number>() {

        @Override
        public void changed(ObservableValue<? extends Number> arg0,
                Number arg1, Number arg2) {
            sc.setLayoutX(arg2.doubleValue()- sc.getWidth()/2 - 1);
            anchorPane.setPrefWidth(arg2.doubleValue() - sc.getWidth());
        }
    });

    // Change the scroll bar and the anchor pane when user change scene's height
    scene.heightProperty().addListener(new ChangeListener<Number>() {

        @Override
        public void changed(ObservableValue<? extends Number> arg0,
                Number arg1, Number arg2) {
            sc.setMax(preHeight - arg2.doubleValue());
            if(arg2.doubleValue() >= preHeight) {
                sc.setVisible(false);
            }
            else {
                sc.setVisible(true);
            }
            sc.setPrefHeight(arg2.doubleValue());
            anchorPane.setPrefHeight(arg2.doubleValue());
        }
    });

    // Change the Y position of anchor pane when user scroll the scroll bar
    sc.valueProperty().addListener(new ChangeListener<Number>() {
        public void changed(ObservableValue<? extends Number> ov,
                Number old_val, Number new_val) {
            anchorPane.setLayoutY(-new_val.doubleValue());
        }
    });

    anchorPane.setPrefSize(scene.getWidth() - sc.getWidth(), scene.getHeight());
}   

There's one issue with this approach, that's if user use tab key to navigate between control in the screen then the Y location of the scroll bar will not change to corresponding position. You may solve this issue by handling focus event for focusable controls in the anchor pane and set Y position for the scroll bar accordingly.

Thinhbk
  • 2,194
  • 1
  • 23
  • 34
  • Year, it's working ! :D Now I'm trying to add a scrollListener. But with this the problem is, when I want to move a component out of the layout, the scrollBars don't move, did you had this problem ? – AwaX Aug 02 '12 at 14:07
  • 1
    For the scrollListener it's good : `this.scene.setOnScroll(new EventHandler() { public void handle(ScrollEvent t) { vBar.setValue(vBar.getValue() - t.getDeltaY()); } });` – AwaX Aug 02 '12 at 15:21
  • Hmm, I got the same problem, too. I suppose you may handle the focus event of the control and navigate the scroll bar to desire position (you have to calculate the position) – Thinhbk Aug 03 '12 at 03:15
  • what is vBar here please explain. – adesh singh Oct 10 '13 at 05:44
  • I used to have that problem. What I did is: I assume you add things to an AnchorPane within the scrollpane. I bind this AnchorPane minimum sizes to be the scrollbar width and height properties. and from the Java FX Scene builder, I set its maximum hight and width to "Max" . then things update as needed. – melkhaldi Feb 21 '14 at 14:39