简体   繁体   中英

Javafx - Bounds are zero until seen

In an attempt to fix a problem with printing within the margins, I'm trying to scale my forms so that they'd shrink to the size of the paper it will be printed to.

Inside Printable.java that extends VBox

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 will be kept in a HashMap data.table . When my printing window is loaded I run scaleToFit for each of them. main is a ScrollPane.

Inside ModPrintCycle.java that extends VBox

//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);
                                }
                            }
                        });
                    }
                });
            }
        });     
    }
});

Just for this example, I also added scaleToFit() in the button that changes between these Printable s. [EDIT: Added the scripts that explicitly show the use of scaleToFit()] Note that data.tables is a HashMap containing the Printables.

Inside ModPrintCycle.java continuation

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
}

However, whenever scaleToFit() is called for the first time (when ModPrintCycle is loaded), it tells me that the widths are 0, thus will not scale yet. The second time it is called (when I change between them for the first time), it's still 0. When it finally runs a 3rd time (when I look back at the Printable ), it finally works and changes the widths as needed.

Since these Printable s need to be printed, I cannot ensure that the forms are scaled until someone looks through all of them twice.

How do I force the forms to take their bounds before having to load them?

Since the code you posted is not fully executable (ie not MCVE or SSCCE), the problem cannot be reproduced. It is also difficult to guess the cause. But I see your purpose, so I suggest instead of scaling it manually, let the printable scale itself automatically through listener:

@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 );
                }
            }
        } );
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM