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

Image 如何将TableView中的文本作为文本数据而不是图像数据打印到PDF?,image,pdf,printing,tableview,javafx-8,Image,Pdf,Printing,Tableview,Javafx 8,我正在开发JavaFX应用程序,它使用JavaFX8PrintJob和打印机API显示一个TableView并输出一个PDF文件。 JDK版本是1.8.0 我希望场景中的所有文本都作为文本数据输出到PDF文件中。 但是,结果是文本被渲染为图像而不是文本数据。 我的系统要求将所有文本存储为文本数据,以便用户可以通过PDF阅读器软件(如Adobe reader)选择和复制它们 问题是我应该如何修改TabeView属性以将文本打印为文本。 我不想将标签放在TableView中的每个单元格上,但如果无法

我正在开发JavaFX应用程序,它使用JavaFX8PrintJob和打印机API显示一个TableView并输出一个PDF文件。 JDK版本是1.8.0

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

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

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

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

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

我发现的唯一一件事是,当在CSS文件中将TableView的“-fx opacity”样式设置为小于1.0(例如0.99)的值时,位于TableView外部的标签(在我的示例中,它显示“Person List”)将作为文本数据输出。 可通过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\u 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>
控制器类: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;}
    }
}
封装测试;
导入java.net.MalformedURLException;
导入java.net.URL;
导入java.util.ResourceBundle;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.collections.ObservableList;
导入javafx.fxml.fxml;
导入javafx.fxml.Initializable;
导入javafx.print.PageLayout;
导入javafx.print.PageOrientation;
导入javafx.print.Paper;
导入javafx.print.Printer;
导入javafx.print.PrinterJob;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.control.cell.PropertyValueFactory;
导入javafx.scene.layout.Pane;
/**
*FXML控制器类。
*/
公共类FxmlController实现可初始化{
@FXML专用窗格根窗格;
@FXML专用窗格printBoundsPane;
@FXML私有表视图表;
@FXML私有表列familyNameColumn;
@FXML私有表列givenNameColumn;
/**
*初始化阶段。
*@param location FXML文件位置
*@param资源
*/
@凌驾
公共void初始化(URL位置、ResourceBundle资源){
//将数据与列链接。
this.familyNameColumn.setCellValueFactory(新的PropertyValueFactory(“familyName”);
this.givenNameColumn.setCellValueFactory(新属性ValueFactory(“givenName”));
//将示例记录添加到TableView
table.getItems().add(newperson(“TEST1”、“TEST1”));
table.getItems().add(newperson(“TEST2”、“TEST2”));
}
/**
*[Reload CSS]按钮的事件侦听器。
*重新加载CSS文件。
*@throws java.net.MalformedURLException
*/
public void reload()引发错误的DurLexException{
//获取样式表列表。
ObservableList styleSheets=this.rootPane.getStylesheets();
//CSS文件位置。
URL cssLocation=新URL(styleSheets.get(0));
//重置CSS文件。
getStylesheets().set(0,cssLocation.toExternalForm());
}
/**
*[Print]按钮的事件侦听器。
*打印出可标识为“printBoundsPane”的窗格。
*/
公开作废印刷品(){
//默认打印机对象。
打印机打印机=打印机。getDefaultPrinter();
//打印页面布局对象。
//*为方便测试,将“横向”设置为页面方向。
//如果输出pdf包含文本信息,则输出文件将以纵向模式显示。
//如果没有,它将以横向模式显示。
PageLayout=printer.createPageLayout(Paper.A4,PageOrientation.横向,printer.MarginType.DEFAULT);
//创建打印机作业。
PrinterJob作业=PrinterJob.createPrinterJob();
如果(作业!=null){
//设置作业名称。
job.getJobSettings().setJobName(“TestPrint”);
if(job.showPrintDialog(this.rootPane.getScene().getWindow())){
//打印出指定的窗格。
作业.printPage(布局,此.printBoundsPane);
}
否则{
System.out.println(“打印已取消”);
}
//完成打印工作。
job.endJob();
}
}
/**
*用于定义一个人的类。
*/
公共静态类人员{
私有最终StringProperty familyName=新的SimpleStringProperty();
private final StringProperty givenName=新SimpleStringProperty();
/**
*构造器。
*@param\u familyName此人的姓氏。
*@param\u givenName该人的名字。
*/
Person(字符串\u familyName,字符串\u givenName){
this.familyName.set(_familyName);
this.givenName.set(_givenName);
}
public StringProperty familyNameProperty(){返回this.familyName;}
public StringProperty givenNameProperty(){返回this.givenName;}
}
}
将JavaFX节点(
printBoundsPane
)发送到打印机p
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;}
    }
}