Javafx - 在看到之前边界为零

Javafx - Bounds are zero until seen

为了解决边距内打印的问题,我正在尝试缩放我的表单,以便它们缩小到要打印到的纸张大小。

在延伸 VBox

Printable.java 内部
public void scaleToFit(){
    double maxWidth = 497.0;

    this.requestLayout();

    double width = this.getWidth();

    if(width > maxWidth){
        double widthFrac = maxWidth / width;
        this.setScaleX(widthFrac);
    }
    System.out.println(this.getWidth());

    //edited out same process for height
}

Printable 将保存在 HashMap data.table 中。当我的打印 window 加载时,我为每个打印 运行 scaleToFitmain 是一个 ScrollPane。

在扩展 VBox

ModPrintCycle.java 内部
//inside constructor

main.sceneProperty().addListener(new ChangeListener<Scene>(){
    @Override
    public void changed(ObservableValue<? extends Scene> observable, Scene oldValue, Scene newValue) {
        System.out.println("new Scene");
        newValue.windowProperty().addListener(new ChangeListener<Window>(){
            public void changed(ObservableValue<? extends Window> arg0, Window arg1, Window arg2) {
                System.out.println("new Window");
                arg2.setOnShown(new EventHandler<WindowEvent>(){
                    @Override
                    public void handle(WindowEvent event) {
                        Platform.runLater(new Runnable(){
                            @Override
                            public void run() {
                                System.out.println(event.toString());
                                lookingAt = data.tables.size();
                                while(lookingAt-1 >= 0 ){
                                    showNext(-1);
                                }
                            }
                        });
                    }
                });
            }
        });     
    }
});

只是为了这个例子,我还在 Printable 之间变化的按钮中添加了 scaleToFit()。 [编辑:添加了明确显示使用 scaleToFit() 的脚本] 请注意,data.tables 是一个包含 Printables 的 HashMap。

内部ModPrintCycle.java延续

private void showNext(int move){
    boolean k = false;

    if(move > 0 && lookingAt+move < data.tables.size()){
        k = true;
    }
    else if(move < 0 && lookingAt+move >=0){
        k = true;
    }

    if(k){
        lookingAt+= move;   
    }       

    show();
}

private void show(){
    if(data.tables.size() > 0){
        if(lookingAt >= 0 && lookingAt < data.tables.size()){
            //tableOrder is an ArrayList<String> for the arrangement of data.tables
            if(tableOrder.size() > 0){
                Printable pt = data.tables.get(tableOrder.get(lookingAt));
                main.setContent(pt);
                pt.scaleToFit();
            }
        }
        else{
            if(lookingAt < 0){
                lookingAt = 0;
                show();
            }
            else if(lookingAt >= data.tables.size()){
                lookingAt = data.tables.size()-1;
                show();
            }
        }

        txtStatus.setText((lookingAt+1) + " / " + data.tables.size());  
    }else{
        main.setContent(null);
        txtStatus.setText("Empty");
    }
}

public void printAll(ArrayList<String> pageList){
    //PrinterJob pj is global
    //conditions and try declarations
        pj = PrinterJob.createPrinterJob(curP);
        PageLayout pp = curP.createPageLayout(Paper.LEGAL, PageOrientation.PORTRAIT, MarginType.DEFAULT);
        PageLayout pl = curP.createPageLayout(Paper.LEGAL, PageOrientation.LANDSCAPE, MarginType.DEFAULT);

        for(String p : pageList){
            Printable pt = data.tables.get(p);
            pt.scaleToFit();
            if(pt.isLandscape()){
                pj.printPage(pl,pt);    
            }
            else{
                pj.printPage(pp,pt);
            }   
        }
        pj.endJob();
    // catch statements
}

但是,每当第一次调用 scaleToFit() 时(加载 ModPrintCycle 时),它告诉我宽度为 0,因此还不会缩放。第二次调用(当我第一次在它们之间切换时),它仍然是 0。当它最终第三次 运行 时(当我回头看 Printable 时),它终于起作用了并根据需要更改宽度。

由于这些 Printable 需要打印,我无法确保表格被缩放,直到有人仔细阅读所有表格。

如何在必须加载表单之前强制其边界?

由于您发布的代码不是完全可执行的(即不是 MCVE 或 SSCCE),因此无法重现该问题。也很难猜测原因。但我明白你的目的,所以我建议不要手动缩放它,而是让可打印的缩放本身通过侦听器自动缩放:

@Override
public void start( Stage stage )
{
    ScrollPane scrollPane = new ScrollPane( new Printable( new Label( "looong loooong loooooong looooong loooong text" ) ) );
    stage.setScene( new Scene( scrollPane ) );
    stage.show();
}


class Printable extends VBox
{
    public Printable( Node... children )
    {
        super( children );

        Printable me = this;
        this.widthProperty().addListener( new ChangeListener<Number>()
        {
            @Override
            public void changed( ObservableValue<? extends Number> observable, Number oldValue, Number newValue )
            {
                double maxWidth = 100.0;
                double width = newValue.doubleValue();
                if ( width > maxWidth )
                {
                    double widthFrac = maxWidth / width;
                    me.setScaleX( widthFrac );
                }
            }
        } );
    }
}