How to print a nice Receipt / Bill using JavaFX and a Thermal Printer?
<p>I know we have this question already but they can't help me at all. How do I create and print a nice Receipt/Bill lite the one on the picture:</p>

<p><a href="http://i.stack.imgur.com/RoNgb.gif" rel="nofollow">Bill Model Here</a></p>

<p>Here is my VOID for printing:</p>

<pre><code>public void ReceiptPrinter(Node node){

    Printer printer = Printer.getDefaultPrinter();

    PageLayout page = printer.getDefaultPageLayout();

    double X = page.getPrintableWidth() / (node.getBoundsInParent().getWidth());
    double Y = page.getPrintableHeight() / (node.getBoundsInParent().getHeight());

    System.out.println("X = "+X);
    System.out.println("Y = "+Y);

    Scale SCL = new Scale(X, Y);
    node.getTransforms().add(SCL);

    PrinterJob PJ = PrinterJob.createPrinterJob(printer);

    if(PJ != null){
        boolean Success = PJ.printPage(page, node);
        if(Success){
            PJ.endJob();
        }
    }
    node.getTransforms().remove(SCL);
}
</code></pre>

<p>Called and executed like this:</p>

<pre><code>new ReceiptPrinter().ReceiptPrinter(My_TableView);
</code></pre>

<p>Here is my full code source:</p>

<pre><code>public class VendaMode1 {

private VBox PnlProduto, PnlFactura;
private GridPane PnlQnt;

private Label LblTitle, LblTitle2, LblDesc, LblPrice;
static TextField TxtSource;

private Label LblTitle3;
private TextField TxtQnt;
private Button CmdOk, CmdCancel, CmdClear; 

private StackPane PnlTable;
private TableView TblProds;
private TableColumn ColDesc, ColPrec, ColQnt, ColSubTtl;

private GridPane PnlPagar;
private Label LblTitlo4, LblTotal;
private Button CmdBorrar, CmdPagar;
private Timeline TL;
private String USER;

public HBox PnlVMode1(HBox PnlVenda, String Func){

    PnlVenda = new HBox();
    PnlVenda.setPadding(new Insets(10,10,10,10));
    PnlVenda.setSpacing(10);
    PnlVenda.setAlignment(Pos.TOP_CENTER);
    PnlVenda.setStyle("-fx-background-color: White;");

    USER = Func;

    if(PnlVenda.isFocused()){
        TxtSource.requestFocus();
    }

    ProdReview();
    PnlVenda.getChildren().add(PnlProduto);

    ProdFactura();
    PnlVenda.getChildren().add(PnlFactura);    

    return PnlVenda;

}    

public void focusCycle(boolean RUN){
    if(RUN==true)TxtSource.requestFocus();
}

public void ProdReview(){

    PnlProduto = new VBox();
    PnlProduto.setPadding(new Insets(10,10,10,10));
    PnlProduto.setSpacing(10);
    PnlProduto.setPrefWidth(500);
    PnlProduto.setStyle("-fx-background-color: Black;");

    if(PnlProduto.isFocused()){
        TxtSource.requestFocus();
    }

        VBox PnlFind = new VBox();
        PnlFind.setAlignment(Pos.CENTER);

            LblTitle = new Label("Codigo");
            LblTitle.setPrefSize(500, 20);
            LblTitle.setAlignment(Pos.CENTER);
            LblTitle.setStyle("-fx-background-color: Grey;");

            TxtSource = new TextField("");
            TxtSource.setPrefSize(500, 80);
            TxtSource.setAlignment(Pos.CENTER);

            LblTitle2 = new Label("Descricao e Preco"); 
            LblTitle2.setPrefSize(500, 20);
            LblTitle2.setAlignment(Pos.CENTER);
            LblTitle2.setStyle("-fx-background-color: Grey;");

            LblDesc = new Label("");
            LblDesc.setPrefSize(500, 40);
            LblDesc.setAlignment(Pos.CENTER);
            LblDesc.setStyle("-fx-background-color: White;");
            LblDesc.setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));

            LblPrice = new Label("");
            LblPrice.setPrefSize(500, 40);
            LblPrice.setAlignment(Pos.CENTER);
            LblPrice.setStyle("-fx-background-color: White;");
            LblPrice.setFont(Font.font("Times New Roman", FontWeight.BOLD, 50));

        PnlFind.getChildren().addAll(LblTitle, TxtSource);
        VBox.setMargin(LblTitle2, new Insets(10, 0,0,0));
        PnlFind.getChildren().addAll(LblTitle2, LblDesc, LblPrice);

            ProdQnt();

        VBox.setMargin(PnlQnt, new Insets(10, 0,0,0));
        PnlFind.getChildren().add(PnlQnt);

        TxtSource.setOnKeyPressed(new EventHandler&lt;KeyEvent&gt;(){
            public void handle(KeyEvent kv){
                if(kv.getCode() == KeyCode.ENTER){

                    getProd();

                    if(LblPrice.getText()==""){
                        TxtQnt.setText("");
                        TxtSource.setText("");
                        TxtSource.requestFocus();

                    }else{
                        TxtQnt.setText("1");
                        TxtQnt.requestFocus();
                    }


                }
            }
        });

    PnlProduto.getChildren().add(PnlFind);

}

public void getProd(){

    Connection Con = null;
    try{
        Con = DBConnection.GetConnection();
    }catch(SQLException ex){
        new MsgBox().MessageBox("Connection Error", ex.getMessage());
    }
        String Query = "Select PrdDescricao, PrdPreco from Produtos Where PrdCodigo = ?";
    try{
        PreparedStatement Sttm = Con.prepareStatement(Query);
        Sttm.setString(1, TxtSource.getText());
        ResultSet Rs = Sttm.executeQuery();

        while(Rs.next()){
            LblDesc.setText(Rs.getString("PrdDescricao"));
            LblPrice.setText(Rs.getString("PrdPreco"));
        }

        Sttm.close();
        Con.close();

    }catch(Exception ex){
        new MsgBox().MessageBox("Connection Error", ex.getMessage());
    }


}

public void ProdQnt(){

    PnlQnt = new GridPane();
    PnlQnt.setGridLinesVisible(true);
    PnlQnt.setVgap(10);
    PnlQnt.setHgap(10);

    ColumnConstraints COL1 = new ColumnConstraints(60,60,60);
    COL1.setHgrow(Priority.NEVER);
    ColumnConstraints COL2 = new ColumnConstraints();

    RowConstraints ROW1 = new RowConstraints(10,10,10);
    ROW1.setVgrow(Priority.NEVER);

    PnlQnt.getColumnConstraints().add(0, COL1);
    PnlQnt.getColumnConstraints().add(1, COL1);
    PnlQnt.getColumnConstraints().add(2, COL1);
    PnlQnt.getColumnConstraints().add(3, COL2);

        LblTitle3 = new Label("Quantidade");
        LblTitle3.setPrefSize(500, 20);
        LblTitle3.setAlignment(Pos.CENTER);
        LblTitle3.setStyle("-fx-background-color: Grey;");

        TxtQnt = new TextField();
        TxtQnt.setFont(Font.font("Times New Roman", FontWeight.BOLD, 50));
        TxtQnt.setPrefSize(500, 115);
        TxtQnt.setAlignment(Pos.CENTER);

        CmdOk = new Button("OK");
        CmdOk.setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));
        CmdOk.setPrefSize(500, 115);
        CmdOk.setAlignment(Pos.CENTER);

        CmdCancel = new Button("Cancel");
        CmdCancel.setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));
        CmdCancel.setPrefSize(500, 115);
        CmdCancel.setPrefSize(500, 50);

        CmdClear = new Button("Clear");
        CmdClear.setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));
        CmdClear.setPrefSize(300, 50);

        Button Char[] = new Button[]{
            new Button("0"),
            new Button("1"),
            new Button("2"),
            new Button("3"),
            new Button("4"),
            new Button("5"),
            new Button("6"),
            new Button("7"),
            new Button("8"),
            new Button("9"),
        };
        for(int i=0; i&lt;10; i++){
            Char[i].setPrefSize(50, 30);
            Char[i].setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));

        }



        CmdClear.setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                TxtQnt.setText("1");
                TxtQnt.requestFocus();
            }
        });

        Char[0].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+0);
            }
        });
        Char[1].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+1);
            }
        });
        Char[2].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+2);
            }
        });
        Char[3].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+3);
            }
        });
        Char[4].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+4);
            }
        });
        Char[5].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+5);
            }
        });
        Char[6].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+6);
            }
        });
        Char[7].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+7);
            }
        });
        Char[8].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+8);
            }
        });
        Char[9].setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                if(LblPrice.getText()==""){
                   TxtSource.requestFocus();
                   return;
                }
                String Qnt = TxtQnt.getText();
                TxtQnt.setText(Qnt+9);
            }
        });

        TxtQnt.setOnKeyPressed(new EventHandler&lt;KeyEvent&gt;(){
            public void handle(KeyEvent kv){
                if(kv.getCode()== KeyCode.ENTER){

                    if(LblPrice.getText()==""){
                        TxtSource.requestFocus();
                        return;
                    }
                    try{
                        Integer.parseInt(TxtQnt.getText());
                    }catch(Exception ex){
                        TxtQnt.requestFocus();
                        return;
                    }
                    getTableVal();
                    TxtSource.setText("");
                    LblDesc.setText("");
                    LblPrice.setText("");
                    TxtQnt.setText("");

                    TxtSource.requestFocus();
                }

            }
        });


        CmdOk.setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){

                if(LblPrice.getText()==""){
                    TxtQnt.setText("");
                    TxtSource.requestFocus();
                    return;
                }
                try{
                    Integer.parseInt(TxtQnt.getText());
                }catch(Exception ex){
                    TxtQnt.setText("1");
                    TxtQnt.requestFocus();
                    return;
                }

                getTableVal();
                TxtSource.setText("");
                LblDesc.setText("");
                LblPrice.setText("");
                TxtQnt.setText("");

                TxtSource.requestFocus();
            }
        });
        CmdCancel.setOnAction(new EventHandler&lt;ActionEvent&gt;(){
            public void handle(ActionEvent ev){
                TxtSource.setText("");
                LblDesc.setText("");
                LblPrice.setText("");
                TxtQnt.setText("");

                TxtSource.requestFocus();



            }
        });

    PnlQnt.add(LblTitle3, 0, 0, 6, 1);

    PnlQnt.add(TxtQnt, 3, 1, 3, 2);
    PnlQnt.add(CmdOk, 3, 3, 3, 2);
    PnlQnt.add(CmdCancel, 3, 5, 3, 1);

    PnlQnt.add(CmdClear, 0, 5, 3, 1);

    PnlQnt.add(Char[1], 0, 1);
    PnlQnt.add(Char[2], 1, 1);
    PnlQnt.add(Char[3], 2, 1);

    PnlQnt.add(Char[4], 0, 2);
    PnlQnt.add(Char[5], 1, 2);
    PnlQnt.add(Char[6], 2, 2);

    PnlQnt.add(Char[7], 0, 3);
    PnlQnt.add(Char[8], 1, 3);
    PnlQnt.add(Char[9], 2, 3);

    PnlQnt.add(Char[0], 1, 4);

}

private double Total;

public void getTableVal(){

    String Desc = null;
    double Price = 0;
    int Qnt = 0;
    double Subtotal = 0;

    try{
        Desc = LblDesc.getText();
        Price = Double.parseDouble(LblPrice.getText()); 
        Qnt = Integer.parseInt(TxtQnt.getText());
        Subtotal = Price * Qnt;
        Total = Total + Subtotal;
    }catch(Exception ex){
        new MsgBox().MessageBox("Erro de Formato", ex.getMessage());
    }
    ObservableList&lt;SellingProdDataFactory&gt; DT = FXCollections.observableArrayList(); 
    DT.addAll(new SellingProdDataFactory(Desc, Price, Qnt, Subtotal));
    TblProds.getItems().addAll(DT);

    LblTotal.setText(String.valueOf(Total));
}

public void ProdFactura(){

    PnlFactura = new VBox();
    PnlFactura.setPadding(new Insets(10,10,10,10));
    PnlFactura.setSpacing(10);
    PnlFactura.setPrefWidth(500);
    PnlFactura.setStyle("-fx-background-color: Black;");

    if(PnlFactura.isFocused()){
        TxtSource.requestFocus();
    }

        ProdTable();

    PnlFactura.getChildren().addAll(PnlTable, PnlPagar);

    TxtSource.requestFocus();

}

public void ProdTable(){

    PnlTable = new StackPane();
    PnlTable.setMaxHeight(365);

        TblProds = new TableView&lt;&gt;();


            ColDesc = new TableColumn&lt;&gt;("Descricao");
                ColDesc.setMinWidth(200);
                ColDesc.setCellValueFactory(new PropertyValueFactory("Descricao"));

            ColPrec = new TableColumn&lt;&gt;("Preco");
                ColPrec.setMinWidth(50);
                ColPrec.setCellValueFactory(new PropertyValueFactory("Price"));

            ColQnt = new TableColumn&lt;&gt;("Qnt");
                ColQnt.setMinWidth(30);
                ColQnt.setCellValueFactory(new PropertyValueFactory("Qnt"));

            ColSubTtl = new TableColumn&lt;&gt;("Subtotal");
                ColSubTtl.setMinWidth(50);
                ColSubTtl.setCellValueFactory(new PropertyValueFactory("Subtotal"));

        TblProds.getColumns().addAll(ColDesc, ColPrec, ColQnt, ColSubTtl);


    PnlTable.getChildren().add(TblProds);

    PnlPagar = new GridPane();
    PnlPagar.setHgap(5);
    PnlPagar.setVgap(10);

        LblTitlo4 = new Label("Total");
        LblTitlo4.setPrefSize(500, 20);
        LblTitlo4.setAlignment(Pos.CENTER);
        LblTitlo4.setStyle("-fx-background-color: Grey;");

        LblTotal = new Label("000.00");
        LblTotal.setPrefSize(500, 80);
        LblTotal.setFont(Font.font("Times New Roman", FontWeight.BOLD, 100));
        LblTotal.setAlignment(Pos.CENTER);
        LblTotal.setStyle("-fx-background-color: White; -fx-text-fill: Red;");

        CmdBorrar = new Button("Borrar");
        //CmdOk.setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));
        CmdBorrar.setPrefSize(200, 50);
        CmdBorrar.setAlignment(Pos.CENTER);

        CmdPagar = new Button("Pagar");
        //CmdPagar.setFont(Font.font("Times New Roman", FontWeight.BOLD, 30));
        CmdPagar.setPrefSize(300, 50);
        CmdPagar.setAlignment(Pos.CENTER);

    PnlPagar.add(LblTitlo4, 0, 0, 3, 1);
    PnlPagar.add(LblTotal, 0, 1, 3, 1);
    PnlPagar.add(CmdBorrar, 0, 2);
    PnlPagar.add(CmdPagar, 1, 2, 2, 1);


    CmdPagar.setOnAction(new EventHandler&lt;ActionEvent&gt;(){
        public void handle(ActionEvent ev){

            if(Total&lt;=0){
                TxtSource.requestFocus();
                return;
            }

          boolean Chk =  new Pagar().Pagar(new Stage(), Total);

          if(Chk == true){

              ReportarVenda.ReportVenda(USER, 2, Total);

              new ReceiptPrinter().ReceiptPrinter(TblProds);

              Total = 0.0;
              TblProds.getItems().clear();
              LblTotal.setText("");
              LblDesc.setText("");
              LblPrice.setText("");
              TxtSource.setText("");
          }
          TxtSource.requestFocus();

        }
    });

    CmdBorrar.setOnAction(new EventHandler&lt;ActionEvent&gt;(){
        public void handle(ActionEvent ev){

              TblProds.getItems().clear();
              Total = 0.0;
              LblTotal.setText("0.0");
              LblDesc.setText("");
              LblPrice.setText("");
              TxtSource.setText("");

              TxtSource.requestFocus();

        }
    });


}

}
</code></pre>