如何将TableView中的文本打印为文本数据而不是将图像数据打印为PDF?

时间:2017-02-27 11:33:52

标签: image pdf printing tableview javafx-8

我正在开发使用JavaFX 8 PrintJob和Printer API显示TableView并输出PDF文件的JavaFX应用程序。 JDK版本是1.8.0。

我希望场景中的所有文本都作为文本数据输出到PDF文件中。 但是,结果是文本被渲染为图像而不是文本数据。 我的系统要求是将所有文本存储为文本数据,以便用户可以通过PDF阅读器软件(如Adobe Reader)进行选择和复制。

问题是如何修改TabeView属性以便将文本作为文本打印。 我不想将标签放在TableView中的每个单元格上,但如果没有办法实现我的目标,我将采用这种不太智能的解决方案。

出于调查目的,我刚刚创建了一个小应用程序,如下所示。 该应用程序包括两个按钮([重新加载CSS]和[打印]按钮),一个标签和一个TableView。

  • [Reload CSS]按钮:为方便测试而设置。修改CSS文件后,测试人员无需重新启动应用程序。在CSS文件更改后检查行为时,请单击此按钮。

  • [打印]按钮:单击时,将显示打印对话框,然后请选择一个PDF创建软件作为打印机,如CubePDF。

我发现只有一件事是,当在CSS文件中使用小于1.0的值(例如0.99)设置TableView的'-fx-opacity'样式时,该标签位于TableView外部(在我的情况下) ,它显示“人员列表”)作为文本数据输出。 可以通过PDF阅读器软件选择文本“人员列表”。 但是,整个TableView呈现为一个图像。 如果提供了一些智能解决方案,我将不胜感激。

主类:PrintApp.java

package test;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 * Main class.
 */
public class PrintApp extends Application {
    /**
     * Start the application.
     * @param stage Stage object
     * @throws Exception Exception
     */
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("person_list.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

FXML文件:person_list.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.net.URL?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.Pane?>

<Pane fx:id="rootPane" prefHeight="400.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.FxmlController">
    <stylesheets>
        <URL value="@style.css" />
    </stylesheets>

    <children>
        <!-- Reload the CSS file -->
        <!-- * User does not need to re-start the application after the CSS file is modified. -->
        <Button layoutX="20.0" layoutY="10.0" onAction="#reload" prefHeight="20.0" prefWidth="80.0" text="Reload CSS" />

        <!-- Print the "printBoundsPane" pane -->
        <Button layoutX="120.0" layoutY="10.0" onAction="#print" prefHeight="20.0" prefWidth="80.0" text="Print" />

        <!-- Target bounds which is printed out. -->
        <!-- * When the [Print] button is clicked, the print dialog will be displayed. -->
        <!--   Then, the following "Pane" will be printed out. -->
        <Pane fx:id="printBoundsPane" layoutX="20.0" layoutY="60.0" prefHeight="300.0" prefWidth="260.0">
            <children>
                <Label layoutX="10.0" layoutY="10.0" text="Person List" />

                <TableView fx:id="table" layoutY="40.0" prefHeight="260.0" prefWidth="260.0" visible="true">
                    <columns>
                        <TableColumn fx:id="familyNameColumn" prefWidth="120.0" text="Family Name" />
                        <TableColumn fx:id="givenNameColumn" prefWidth="120.0" text="Given Name" />
                    </columns>
                </TableView>
            </children>
        </Pane>

    </children>
</Pane>

CSS文件:style.css

/**
 * Root pane.
 */
#rootPane {
    -fx-background-color: white;
}

/**
 * Actual bounds which is printed out.
 */
#printBoundsPane {
    -fx-border-color: darkgray;
    -fx-border-width: 1px;
}

/**
 * Whole TableView.
 */
.table-view {
    -fx-opacity: 0.99;
}

控制器类:FxmlController.java

package test;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.print.PageLayout;
import javafx.print.PageOrientation;
import javafx.print.Paper;
import javafx.print.Printer;
import javafx.print.PrinterJob;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Pane;

/**
 * FXML Controller class.
 */
public class FxmlController implements Initializable {
    @FXML private Pane rootPane;
    @FXML private Pane printBoundsPane;
    @FXML private TableView<Person> table;
    @FXML private TableColumn<Person, String> familyNameColumn;
    @FXML private TableColumn<Person, String> givenNameColumn;

    /**
     * Initialize the stage.
     * @param location FXML file location
     * @param resources resources
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // Link the data with a column.
        this.familyNameColumn.setCellValueFactory(new PropertyValueFactory("familyName"));
        this.givenNameColumn.setCellValueFactory(new PropertyValueFactory("givenName"));

        // Add sample records to the TableView
        table.getItems().add(new Person("TEST1", "test1"));
        table.getItems().add(new Person("TEST2", "test2"));
    }

    /**
     * Event listener for [Reload CSS] button.
     * Reload the CSS file.
     * @throws java.net.MalformedURLException
     */
    public void reload() throws MalformedURLException {
        // Get the stylesheet list.
        ObservableList<String> styleSheets = this.rootPane.getStylesheets();

        // CSS file location.
        URL cssLocation = new URL(styleSheets.get(0));

        // Reset the CSS file.
        rootPane.getStylesheets().set(0, cssLocation.toExternalForm());
    }

    /**
     * Event listener for [Print] button.
     * Print out the pane which can be identified as "printBoundsPane".
     */
    public void print() {
        // Default printer object.
        Printer printer = Printer.getDefaultPrinter();

        // Print page layout object.
        // * Set "LANDSCAPE" as the page orientation for the convenience for the test.
        //   If the output pdf has the text information, the output file is shown in a PORTRAIT mode.
        //   If not, it will be shown in a LANDSCAPE mode.
        PageLayout layout = printer.createPageLayout(Paper.A4, PageOrientation.LANDSCAPE, Printer.MarginType.DEFAULT);

        // Create a printer job.
        PrinterJob  job = PrinterJob.createPrinterJob();

        if (job != null) {
            // Set the job name.
            job.getJobSettings().setJobName("TestPrint");

            if (job.showPrintDialog(this.rootPane.getScene().getWindow())) {
                // Print out the specified pane.
                job.printPage(layout, this.printBoundsPane);
            }
            else {
                System.out.println("Print canceled.");
            }

            // Finish the print job.
            job.endJob();
        }
    }

    /**
     * The class for defining a person.
     */
    public static class Person {
        private final StringProperty familyName = new SimpleStringProperty();
        private final StringProperty givenName = new SimpleStringProperty();

        /**
         * Constructor.
         * @param _familyName Family name of the person.
         * @param _givenName Given name of the person.
         */
        Person(String _familyName, String _givenName) {
            this.familyName.set(_familyName);
            this.givenName.set(_givenName);
        }

        public StringProperty familyNameProperty() {return this.familyName;}
        public StringProperty givenNameProperty() {return this.givenName;}
    }
}

0 个答案:

没有答案