在自己的页面上打印多个AnchorPanes

问题描述 投票:0回答:1

我有一个 javafx TabPane,我希望能够打印它。 TabPane 有两个选项卡,我希望每个选项卡都打印在自己的页面上。我使用 onAction 函数在其中一个选项卡上创建了一个按钮,以运行名为 onPrint 的方法。该按钮将在一个选项卡中打印一个表格,在另一个选项卡中打印另一个表格。

printer.fxml 文件

<ScrollPane fx:id="assessment"/>
    <Pane fx:id="printPane">
    <TabPane prefHeight="900.0" prefWidth="937.0" tabClosingPolicy="UNAVAILABLE">
        <Tab text="Issues">
                <AnchorPane fx:id="issuesTab" minHeight="0.0" minWidth="0.0" prefHeight="519.0" prefWidth="585.0">
                 <Text text="here is some text" />
                 <Button fx:id="print" layoutX="82.0" layoutY="60.0" mnemonicParsing="false" onAction="#onPrint" text="print" /> 
                </AnchorPane>
        </Tab>
        <Tab text="Function">
                <AnchorPane fx:id="FunctionTab" prefHeight="400.0" prefWidth="600.0">
                     <Text text="here is some text"/>
                </AnchorPane>
        </Tab>
</Pane>
</Scrollpane>

我尝试了几种不同的方法来使其正常工作。我将在下面介绍它们。

打印机控制器文件如下:

public ScrollPane assessment; 
public Pane printerPane; 
public AnchorPane issuesTab;
public AnchorPane functionTab;


 public void onPrint(ActionEvent event) {
        printPane.getChildren().addAll(issuesTab, functionTab);
        Printer printer = Printer.getDefaultPrinter();
        PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
        PrinterJob job = PrinterJob.createPrinterJob();
        job.getJobSettings().setPageRanges(new PageRange(1, 2));
        if (job.showPrintDialog(printPane.getScene().getWindow())){
            boolean success = job.printPage(pageLayout, printPane);
            if (success) {
                job.endJob();
            }
        }
    }

目前这可行,但它将两个表添加到彼此之上。我尝试使用 setPageRanges 函数来设置页面范围,但无法使其正常工作。

然后我想也许我需要为每个选项卡创建一个全新的窗格,然后将它们添加到一个组中,然后它将单独打印。

    private Node toPrint;

    private Node printAllPages(){
        if(toPrint== null){
            Group group = new Group();
            group.getChildren().addAll(
                    new Pane(issuesTab),
                    new Pane(functionTab)
            );
            notToPrint = group;
        }
        return notToPrint;
    }
 public void onPrint(ActionEvent event) {
        PrinterJob job = PrinterJob.createPrinterJob();
        if(job.showPrintDialog(notToPrint.getScene().getWindow())){
            boolean success = job.printPage(printAllPages());
            if(success){
                job.endJob();
            }
        }


    }

然而,这会导致以下错误 - 原因为:java.lang.NullPointerException:无法调用“javafx.scene.Node.getScene()”,因为“this.notToPrint”为空。我也不认为这是正确的方法。

是否需要应用任何 Printer、PageLayout 或 PrinterJob 设置,以便每个 AnchorPane 都可以打印在单独的页面上?


所做的编辑:

根据 @SedJ601 关于如何解决此问题的建议。我浏览了他提供的链接并决定尝试这个 -

PrintController.java

    public TabPane allTabs;
   Printer printer = Printer.getDefaultPrinter();
        PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.DEFAULT);
        PrinterJob job = PrinterJob.createPrinterJob();

        if(job.showPrintDialog(allTabs.getScene().getWindow())){
            double pagePrintableHeight = pageLayout.getPrintableHeight();
            double pagePrintableWidth = pageLayout.getPrintableWidth();
            double scaleX = pagePrintableWidth / allTabs.getBoundsInParent().getWidth();
            double localScale = scaleX;


            double numberOfPages = Math.ceil((allTabs.getPrefWidth()) * localScale) / pagePrintableHeight;
            System.out.println(numberOfPages);

            for(int i = 0; i < numberOfPages; i++){ job.printPage(pageLayout, allTabs.get(i)); } job.endJob();
        }else{
            System.out.println("This did not work");
        }

打印.fxml

<ScrollPane fx:id="assessment">
<TabPane fx:id="allTabs" prefHeight="900.0" prefWidth="937.0" tabClosingPolicy="UNAVAILABLE">
    <Tab text="Issues">
        <content>
            <AnchorPane fx:id="issuesTab" minHeight="0.0" minWidth="0.0" prefHeight="519.0" prefWidth="585.0">
             <Text text="some text" />
            </AnchorPane>
        </content>
    </Tab>
    <Tab text="Function">
        <content>
            <AnchorPane fx:id="functionTab" prefHeight="400.0" prefWidth="600.0">
               <Text text="some text" />
            </AnchorPane>
        </content>
    </Tab>
</TabPane>

但是,这仅打印第一个选项卡。我尝试将 numberOfPages 值设置为 10.0,但仍然只打印第一个选项卡。如何编辑 for 循环以循环遍历两个选项卡或更改 numberOfPages 以准确查找所有页面?

javafx fxml
1个回答
0
投票

如果你只有两个

Tabs
那么我认为下面的代码应该可以工作。

public void onPrint(ActionEvent event) {
        printPane.getChildren().addAll(issuesTab, functionTab);
        Printer printer = Printer.getDefaultPrinter();
        PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
        PrinterJob job = PrinterJob.createPrinterJob();
        job.getJobSettings().setPageRanges(new PageRange(1, 2));
        if (job.showPrintDialog(printPane.getScene().getWindow())){
            //if the number of tabs is variable use a loop and print each tab.
            boolean success = job.printPage(pageLayout, issuesTab);
            boolean successTwo = job.printPage(pageLayout, functionTab);
            if (success && successTwo) {
                job.endJob();
            }
            else{
                System.out.println("Printing Error!");
           }
        }
    }

我在这里输入了上面的代码,但没有进行测试。可能有错误。

这是一个MCVE

//Original code from https://jenkov.com/tutorials/javafx/tabpane.html
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.print.PageLayout;
import javafx.print.PageOrientation;
import javafx.print.Paper;
import javafx.print.Printer;
import javafx.print.PrinterJob;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TabPane;
import javafx.scene.control.Tab;
import javafx.scene.control.Label;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class App extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        List<Node> nodesToBePrinted = new ArrayList();
        
        TabPane tabPane = new TabPane();
        VBox.setVgrow(tabPane, Priority.ALWAYS);
        
        StackPane stackPane1 = new StackPane(new Label("This is tab 1"));
        nodesToBePrinted.add(tabPane);
        StackPane stackPane2 = new StackPane(new Label("This is tab 2"));
        nodesToBePrinted.add(stackPane2);
        StackPane stackPane3 = new StackPane(new Label("This is tab 3"));
        nodesToBePrinted.add(stackPane3);
        Tab tab1 = new Tab("Tab 1", stackPane1);
        Tab tab2 = new Tab("Tab 2"  , stackPane2);
        Tab tab3 = new Tab("Tab 3" , stackPane3);

        tabPane.getTabs().add(tab1);
        tabPane.getTabs().add(tab2);
        tabPane.getTabs().add(tab3);

        
        VBox root = new VBox(tabPane);
        Scene scene = new Scene(root, 500, 500);
        
        Button button = new Button("Print Nodes");
        button.setOnAction(actionEvent -> {
            printNodes(nodesToBePrinted, scene);
        });        
        root.getChildren().add(button);
        
        

        primaryStage.setScene(scene);
        primaryStage.setTitle("JavaFX App");

        primaryStage.show();
    }
    
    
    public void printNodes(List<Node> nodesFromSameScene, Scene scene)
    {
        boolean control = true;
        
        Printer printer = Printer.getDefaultPrinter();
        PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
        PrinterJob job = PrinterJob.createPrinterJob();
        
        if (job.showPrintDialog(scene.getWindow()))
        {
            for(int i = 0; i < nodesFromSameScene.size(); i++)
            {
                if(!job.printPage(pageLayout, nodesFromSameScene.get(i)))
                {
                    control = false;
                    break;
                }            
            }

            if(control)
            {
                job.endJob();
            }
            else
            {
                System.out.println("Printing Error!");
            }
        }
        
    }
}

输出 - 保存为 PDF 而不是打印!

© www.soinside.com 2019 - 2024. All rights reserved.