簡體   English   中英

如何在JavaFX 8中獲取Label對象在ScrollPane中的位置

[英]How to get the position of a Label object inside a ScrollPane in JavaFX 8

我在VBox內包含一些標簽,然后將VBox放入“滾動窗格”中。 我可以通過在滾動窗格上調用setVvalue()來進行滾動窗格自動滾動。 所以我想要的是,當Label對象開始靠近滾動窗格的頂部邊緣或底部邊緣時,它應該開始淡出(降低其不透明度),因為它在滾動窗格中移出了視野。 我正在努力找出如何實現此邏輯,是否有某種方法可以找出對象在滾動窗格中的位置? 或者這會變得更復雜。 任何幫助,將不勝感激!

我對如何實現這一目標進行了一些研究,並提出了以下建議:

您可以將添加ChangeListenervvalueProperty的的scrollPane每次觸發scrollPane滾動。 在這里,我們需要檢查是否有任何標簽位於視圖的頂部或底部邊緣。 我遇到了這篇文章該文章提供了一種獲取子元素的可見范圍的方法。

經過反復試驗,我發現最靠近邊緣的minYmaxY值的標簽在靠近邊緣時接近零。 通過使用此選項,可以根據它們與邊緣的接近程度來更改它們的不透明度。 我為應更改不透明度設置了閾值,但是您也可以指定常數值。 這是我最終得到的圖像:

在此處輸入圖片說明

這是所有代碼:

主班:

public class Main extends Application{

    public static Stage primaryStage;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Main.primaryStage=primaryStage;
        AnchorPane page = (AnchorPane) FXMLLoader.load(MainController.class.getResource("mainFXML.fxml"));

        Scene scene = new Scene(page);

        primaryStage.setTitle("Fade example");
        primaryStage.setScene(scene);

        // Stage positioning
        Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();

        // stage positioning
        primaryStage.setX(primaryScreenBounds.getMaxX()*5/8);
        primaryStage.setY(primaryScreenBounds.getMinY() + page.getPrefHeight()*2/4);

        primaryStage.show();

    }

    public static void main(String[] args) {

        launch(args);
    }
}

控制器:

public class MainController {

    private static final double FADE_THRESHOLD = 80;

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private ScrollPane scrollPane;

    @FXML
    private AnchorPane rootPane;


    @FXML
    private VBox vBox;


    @FXML
    void initialize() {
        assert vBox != null : "fx:id=\"vBox\" was not injected: check your FXML file 'MainFXML.fxml'.";
        assert scrollPane != null : "fx:id=\"scrollPane\" was not injected: check your FXML file 'MainFXML.fxml'.";
        assert rootPane != null : "fx:id=\"rootPane\" was not injected: check your FXML file 'MainFXML.fxml'.";


        ArrayList<Label> labels = new ArrayList<>();

        for (int i = 0; i < 300; i++) {
            Label l = new Label("Label "+i);
            l.setBackground(new Background(new BackgroundFill(Color.AQUA, CornerRadii.EMPTY, Insets.EMPTY)));
            labels.add(l);
        }

        labels.forEach( e-> vBox.getChildren().add(e));

        scrollPane.vvalueProperty().addListener(new ChangeListener<Number>() 
        {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) 
            {

                //System.out.println("bounds: "+getVisibleBounds(labels.get(51)));

                for(Label l: labels) {
                    Bounds bounds = getVisibleBounds(l);
                    double minY = bounds.getMinY();
                    double maxY = bounds.getMaxY();

                    if(Math.abs(minY) < FADE_THRESHOLD ) {
                        l.setOpacity(1-(FADE_THRESHOLD-Math.abs(minY))/FADE_THRESHOLD);
                    }else if(Math.abs(maxY) < FADE_THRESHOLD) {
                        l.setOpacity(1-(FADE_THRESHOLD-Math.abs(maxY))/FADE_THRESHOLD);
                    }else {
                        l.setOpacity(1);
                    }
                }
            }
        });
    }

    public static Bounds getVisibleBounds(Node aNode)
    {
        // If node not visible, return empty bounds
        if(!aNode.isVisible()) return new BoundingBox(0,0,-1,-1);

        // If node has clip, return clip bounds in node coords
        if(aNode.getClip()!=null) return aNode.getClip().getBoundsInParent();

        // If node has parent, get parent visible bounds in node coords
        Bounds bounds = aNode.getParent()!=null? getVisibleBounds(aNode.getParent()) : null;
        if(bounds!=null && !bounds.isEmpty()) bounds = aNode.parentToLocal(bounds);
        return bounds;
    }
}

和MainFXML.fxml:

<AnchorPane fx:id="rootPane" prefHeight="408.0" prefWidth="330.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
   <children>
      <ScrollPane fx:id="scrollPane" layoutX="28.0" layoutY="14.0" prefHeight="372.0" prefWidth="283.0">
         <content>
            <VBox fx:id="vBox" prefWidth="281.0" />
         </content>
      </ScrollPane>
   </children>
</AnchorPane>

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM