【问题标题】:Javafx 8 Scrollpane content headers not position correctlyJavafx 8 Scrollpane 内容标题位置不正确
【发布时间】:2015-01-08 23:31:41
【问题描述】:

目标是显示类似表格的内容,但在这种情况下,有两组标签,普通的垂直标签和水平标签,两者必须能够滚动并始终保持标签可见。

我以为我已经弄清楚了,它在开始时有效,但是您滚动的次数越多,横幅越偏离位置,它似乎在很长一段时间内的定位中积累了一些错误..这里不知道,或者如果我做错了什么..

在 Win7 上运行 javafx 8.25

我的代码:

package com.hdk.tests;

import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;



public class TestScrollPaneBanners extends Application {

boolean photoYInited = false;
boolean photoHInited = false;

ImageView photoY ;
ImageView photoX;
@Override
public void start(Stage primaryStage) {
    ScrollPane scrollPane = new ScrollPane();
    scrollPane.setPrefSize(400, 400);
    scrollPane.setMaxSize(400, 400);

    BorderPane panel = new BorderPane();
    panel.setPrefSize(600, 600);
    HBox horizontalStripp= new HBox();
     horizontalStripp.setPrefHeight(35);
     horizontalStripp.setMaxWidth(Double.MAX_VALUE);
    horizontalStripp.getChildren().add(new Label("Vertical"));
    HBox header = new HBox();
    HBox.setHgrow(header, Priority.ALWAYS);
     header.setMaxWidth(Double.MAX_VALUE);
    header.setStyle("-fx-background-color:red;");
    Label tl = new Label("This is the top label.....");
    tl.setMaxWidth(Double.MAX_VALUE);
    header.getChildren().add(tl);
    horizontalStripp.getChildren().add(header);


    panel.setTop(horizontalStripp);
    scrollPane.setContent(panel);
    VBox verticalStripp = new VBox();
    verticalStripp.setStyle("-fx-background-color:blue;");
    verticalStripp.getChildren().add(new Label("Vertical"));
    verticalStripp.getChildren().add(new Label("Vertical"));
    verticalStripp.getChildren().add(new Label("Vertical"));
    verticalStripp.getChildren().add(new Label("Vertical"));
    verticalStripp.getChildren().add(new Label("Vertical"));
    verticalStripp.getChildren().add(new Label("Vertical"));
    panel.setLeft(verticalStripp);



    Label infoX = new Label();
    Label infoY = new Label();
    scrollPane.vvalueProperty().addListener( new InvalidationListener(){

        @Override
        public void invalidated(Observable observable) {

            double visibleHeight = panel.getHeight()-scrollPane.getPrefHeight();             
            double posX = visibleHeight*scrollPane.getVvalue();
            boolean visible = posX<header.getHeight();
              String tx ="VisibleY ="+ visible+ " V ="+scrollPane.getVvalue() ;               
            if(!visible){
                //take photo
                if(!photoYInited){
                    //init image
                      WritableImage sns = header.snapshot(new SnapshotParameters(), null);
                        photoY = new ImageView(sns);
                        photoYInited = true;
                        panel.getChildren().add(photoY);
                }
               //position image in borderpane               
                   photoY.setLayoutY(posX);              
                   photoY.setLayoutX(header.getLayoutX());
                   tx+=" Cx "+header.getLayoutX()+" Cy "+posX;
            }else{
                //its visible
                //remove photo if present
                if(photoYInited){
                    panel.getChildren().remove(photoY);
                    photoYInited = false;
                }
            }
             infoY.setText(tx);

        }

    });
    scrollPane.hvalueProperty().addListener( new InvalidationListener(){

        @Override
        public void invalidated(Observable observable) {      

            double visibleWidth = panel.getWidth()-scrollPane.getWidth();

            double posX = visibleWidth*scrollPane.getHvalue();
            boolean visible = posX < verticalStripp.getWidth();
              String tx ="VisibleX ="+ visible+ " H ="+scrollPane.getHvalue() ;

            if(!visible){
                //take photo
                if(!photoHInited){
                    //init image
                      WritableImage sns = verticalStripp.snapshot(new SnapshotParameters(), null);
                        photoX = new ImageView(sns);
                        photoHInited = true;
                        panel.getChildren().add(photoX);
                }               
                   photoX.setLayoutX(posX);
                   photoX.setLayoutY(verticalStripp.getLayoutY());                    
                   tx+=" Cx "+posX+" Cy "+verticalStripp.getLayoutY();
            }else{
                //its visible
                //remove photo if present
                if(photoHInited){
                    panel.getChildren().remove(photoX);
                    photoHInited = false;
                }
            }
             infoX.setText(tx);

        }

    });       
    VBox all = new VBox();
    all.getChildren().add(scrollPane);
    all.getChildren().add(infoX);
    all.getChildren().add(infoY);     

    Scene scene = new Scene(all, 400, 500);

    primaryStage.setTitle("Hello Banner!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

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

}

【问题讨论】:

    标签: javafx-8 scrollpane


    【解决方案1】:

    看起来您正在将 BorderPane 放入 ScrollPane 中。我猜这种组合可能无法按预期工作。请注意,ScrollPane 是一个控件,而不是像 BorderPane 那样的窗格。为什么它不起作用可能在于这些类如何处理它们的大小调整等的技术细节,你可能很难弄清楚。我建议尝试其他方法,从您的描述中并不清楚您想要实现什么。

    【讨论】:

    • 感谢您的反馈!我想过这个问题,但似乎不合逻辑,但编程并不总是合乎逻辑的..将在另一个窗格中尝试一下,也许这就是问题所在..
    【解决方案2】:

    为什么不考虑开源项目?喜欢fxcontrols 上面的屏幕截图是电子表格视图,这是你想要的吗?

    【讨论】:

    • 不完全是,我的需求更像是 swing 中的滚动窗格,带有列和行标题。我在 javafx 中做了一个解决方案,但忘记在此处发布,没有与该功能等效的 javafx我正在写作的时间。
    【解决方案3】:

    注意:由于某种有线原因,StackExchange 无法显示我的整个代码。无论如何,访问此处查看完整代码http://pastebin.com/87rsNyAA

    添加一个边框窗格。在 BorderPane 的中心,添加 ScrollPane。在 BorderPane 的顶部和左侧,添加两个 Pane for Horizo​​ntal 和 Vertical 规则。现在从 ScrollPane 的 HValue 和 VValue 属性中,获取这些 HValue 和 VValue 并相应地更改水平/垂直窗格在顶部或左侧的位置。

    Application Preview

    
    
        import javafx.application.Application;
        import javafx.geometry.Insets;
        import javafx.scene.Scene;
        import javafx.scene.control.ScrollPane;
        import javafx.scene.effect.DropShadow;
        import javafx.scene.layout.Background;
        import javafx.scene.layout.BackgroundFill;
        import javafx.scene.layout.BorderPane;
        import javafx.scene.layout.CornerRadii;
        import javafx.scene.layout.Pane;
        import javafx.scene.paint.Color;
        import javafx.stage.Stage;
        import javafx.stage.Screen;
        import javafx.scene.text.Text;
        import javafx.beans.value.ChangeListener;
        import javafx.beans.value.ObservableValue;
        import javafx.scene.shape.Line;
    
        /**
         *
         * @author Zunayed Hassan
         */
        public class ScrollPaneWithRuler extends Application {
    
            final static double DPI = Screen.getPrimary().getDpi();
            final static double THICKNESS_OF_RULER = DPI * 0.5;
            final static int WINDOW_WIDTH = 1024;
            final static int WINDOW_HEIGHT = 768;
            final static int CONTENT_WIDTH = 2500;
            final static int CONTENT_HEIGHT = 2500;
    
            @Override
            public void start(Stage primaryStage) {        
                BorderPane root = new BorderPane();
    
                // Inside of the scroll pane
                ScrollPane scrollPane = new ScrollPane();
                scrollPane.setStyle("-fx-background: gray;");
                scrollPane.setPrefViewportWidth(800);
                scrollPane.setPrefViewportHeight(600);
                root.setCenter(scrollPane);
    
                Pane artBoard = new Pane();
                artBoard.setPrefSize(CONTENT_WIDTH, CONTENT_HEIGHT);
                scrollPane.setContent(artBoard);
    
                Pane canvas = new Pane();
                canvas.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY)));
                canvas.setPrefSize(600, 500);
                canvas.setEffect(new DropShadow(5, 1, 1, Color.BLACK));
                canvas.setTranslateX(50);
                canvas.setTranslateY(50);
                artBoard.getChildren().add(canvas);
    
                // ----------------------------------------------------------------
    
    
                // Row Header
                Pane verticalRulePane = new Pane();
                verticalRulePane.setBackground(new Background(new BackgroundFill(Color.web("#F4F4F4"), CornerRadii.EMPTY, Insets.EMPTY)));
                root.setLeft(verticalRulePane);
    
                Pane vRule = new Pane();
                vRule.setPrefWidth(THICKNESS_OF_RULER);
                verticalRulePane.getChildren().add(vRule);
    
                for (int i = 0; i  changeListenerForHorizontalScroll = new ChangeListener() {
                    @Override
                    public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                        hRule.setTranslateX(-((CONTENT_WIDTH - WINDOW_WIDTH) * scrollPane.getHvalue()));
                    }
                };
    
                scrollPane.hvalueProperty().addListener(changeListenerForHorizontalScroll);
    
                ChangeListener changeListenerForVerticalScroll = new ChangeListener() {
                    @Override
                    public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                        vRule.setTranslateY(-((CONTENT_HEIGHT - WINDOW_HEIGHT) * scrollPane.getVvalue()));
                    }
                };
    
                scrollPane.vvalueProperty().addListener(changeListenerForVerticalScroll);
    
                // ----------------------------------------------------------------
    
                Scene scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
    
                primaryStage.setTitle("ScrollPane with Ruler");
                primaryStage.setScene(scene);
                primaryStage.show();
            }
    
            /**
             * @param args the command line arguments
             */
            public static void main(String[] args) {
                launch(args);
            }
    
        }
    
    

    【讨论】:

      猜你喜欢
      • 2017-02-11
      • 1970-01-01
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 2016-08-11
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      相关资源
      最近更新 更多