JavaFX - ScrollPane с помощью StackPane - дочерние элементы StackPane не отображаются при изменении viewportBounds

RobRoy спросил: 12 мая 2018 в 03:55 в: javafx

Итак, основная проблема, которую я испытываю, - это щелкнуть по кнопке ScrollBar. Видовой экран Scrollpane изменяется, но не дочерние (Node) на панели. Мне нужно либо запросить фокус на панели, либо щелкнуть по значок в taskmenu, чтобы содержимое содержимого Viewport обновилось. Это происходит автоматически при перемещении полос прокрутки.

Есть ли другой способ получить эту функциональность, как описано выше, и кодом? Запрос вызоваFocus () мне кажется странным. Кстати, он выделяется каждый раз, когда это беспокоит.

Вот что я получил до сих пор:

public class ScrollPaneTest extends Application {
private ScrollPane scrollPane;
private StackPane stackPane;
private Pane pane;
private Button button;@Override
public void start(Stage primaryStage) throws Exception {    scrollPane = new ScrollPane();
    stackPane = new StackPane();
    pane = new Pane();
    button = new Button();    scrollPane.setPrefHeight(400.0);
    scrollPane.setPrefWidth(600.0);    stackPane.setPrefHeight(1000.0);
    stackPane.setPrefWidth(1000.0);    pane.setPrefHeight(200.0);
    pane.setPrefWidth(200.0);    button.setMnemonicParsing(false);
    button.setText("Button");    pane.getChildren().add(button);
    stackPane.getChildren().add(pane);            scrollPane.setContent(stackPane);          scrollPane.viewportBoundsProperty().addListener(new ChangeListener() {
        @Override
        public void changed(ObservableValue observable, Object oldValue, Object newValue) {
            Bounds oldViewportBounds = (Bounds) oldValue;
            Bounds newViewportBounds = (Bounds) newValue;                   double x = newViewportBounds.getMinX() * -1;
            double y = newViewportBounds.getMinY() * -1;            button.setLayoutX(x);
            button.setLayoutY(y);            // Working if focus is requested ...
            //pane.requestFocus();
            // ... or when clicked on the application icon in the taskmenu of windows            // Doesn't work
            //pane.requestLayout();        }
    });    VBox vbox = new VBox();
    vbox.setPrefHeight(400.0);
    vbox.setPrefWidth(600.0);    vbox.getChildren().add(scrollPane);    Scene scene = new Scene(vbox);
    primaryStage.setScene(scene);
    primaryStage.show();        }public static void main(String[] args) {
    launch(args);
} }

В целях иллюстрации:

Кнопка прокрутки не нажата

Кнопка прокрутки дважды нажата

1 ответ

RobRoy ответил: 13 мая 2018 в 06:42

Спасибо Stackoverflow за эту замечательную статью: окно просмотра виджета JavaFX ScrollPaneBounds на прокрутке

С этим я смог найти нужное мне решение. Смотрите ниже:

public class ScrollPaneTest extends Application {private ScrollPane scrollPane;
private StackPane stackPane;
private Pane pane;
private Button button;@Override
public void start(Stage primaryStage) throws Exception {    scrollPane = new ScrollPane();
    stackPane = new StackPane();
    pane = new Pane() {
        @Override
        protected void layoutChildren(){              
            super.layoutChildren();
            // System.out.println("layout children");  
            // more ToDo's if neccessary...
        }
    };    // so that the Pane can be smaller than (potentionally) other Panes inside of the StackPane        
    pane.setManaged(false);
    // set the dimension of the ScrollPane
    pane.setPrefHeight(400.0);
    pane.setPrefWidth(600.0);            button = new Button();
    button.setLayoutX(25);
    button.setLayoutY(25);    scrollPane.setPrefHeight(400.0);
    scrollPane.setPrefWidth(600.0);    stackPane.setPrefHeight(1000.0);
    stackPane.setPrefWidth(1000.0);    button.setMnemonicParsing(false);
    button.setText("Button");    pane.getChildren().add(button);
    stackPane.getChildren().add(pane);            scrollPane.setContent(stackPane);    scrollPane.hvalueProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
            //System.out.println("observable " + observable + " oldValue " + oldValue + " " + "newValue " + newValue);
            double hmin = scrollPane.getHmin();
            double hmax = scrollPane.getHmax();
            double hvalue = scrollPane.getHvalue();
            double contentWidth = scrollPane.getContent().getLayoutBounds().getWidth();
            double viewportWidth = scrollPane.getViewportBounds().getWidth();            double hoffset = 
            Math.max(0, contentWidth - viewportWidth) * (hvalue - hmin) / (hmax - hmin);            pane.setLayoutX(hoffset);
            pane.requestLayout();                
        }
    });            scrollPane.vvalueProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
            //System.out.println("observable " + observable + " oldValue " + oldValue + " " + "newValue " + newValue);
            double vmin = scrollPane.getVmin();
            double vmax = scrollPane.getVmax();
            double vvalue = scrollPane.getVvalue();
            double contentHeight = scrollPane.getContent().getLayoutBounds().getHeight();
            double viewportHeight = scrollPane.getViewportBounds().getHeight();            double voffset = 
            Math.max(0, contentHeight - viewportHeight) * (vvalue - vmin) / (vmax - vmin);            pane.setLayoutY(voffset);
            pane.requestLayout();
        }
    });    VBox vbox = new VBox();
    vbox.setPrefHeight(400.0);
    vbox.setPrefWidth(600.0);    vbox.getChildren().add(scrollPane);    Scene scene = new Scene(vbox);
    primaryStage.setScene(scene);
    primaryStage.show();        }public static void main(String[] args) {
    launch(args);
}
}

К сожалению, я не смог поддержать решение г-на Джеймса_D, но я пытаюсь связать эти оба варианта использования.

Надеюсь, что эта помощь поможет другим , Ура!