printing half of the panel

92 Views Asked by At

Good Evening stack overflow,

I'm trying to print Jpanel on the "zebra gk420t" printer but when i gave it the order its only print the half of my panel like in Image.

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import javax.swing.*;

public class PrintView extends javax.swing.JFrame {
    public PrintView() {
        initComponents();
    }
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel3 = new javax.swing.JPanel();
        barcode_img1 = new javax.swing.JLabel();
        ItemNum_result1 = new javax.swing.JLabel();
        ItemPriceVat_resukt1 = new javax.swing.JLabel();
        barcode_lbl1 = new javax.swing.JLabel();
        ItemName_result1 = new javax.swing.JLabel();
        jSeparator2 = new javax.swing.JSeparator();
        exDate_result1 = new javax.swing.JLabel();
        jButton2 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel3.setBackground(new java.awt.Color(255, 255, 255));
        jPanel3.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(51, 51, 51)));
        jPanel3.setForeground(new java.awt.Color(255, 255, 255));

        barcode_img1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        barcode_img1.setText("Barcode");

        ItemNum_result1.setFont(new java.awt.Font("Segoe UI", 0, 36)); // NOI18N
        ItemNum_result1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        ItemNum_result1.setText("Item Name");
        ItemNum_result1.setToolTipText("");
        ItemNum_result1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        ItemPriceVat_resukt1.setFont(new java.awt.Font("Segoe UI", 1, 36)); // NOI18N
        ItemPriceVat_resukt1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        ItemPriceVat_resukt1.setText("500");
        ItemPriceVat_resukt1.setToolTipText("");

        barcode_lbl1.setFont(new java.awt.Font("Segoe UI", 1, 24)); // NOI18N
        barcode_lbl1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        barcode_lbl1.setText("Baarcode number");

        ItemName_result1.setFont(new java.awt.Font("Segoe UI", 0, 36)); // NOI18N
        ItemName_result1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        ItemName_result1.setText("123123123");
        ItemName_result1.setToolTipText("");
        ItemName_result1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        jSeparator2.setBackground(new java.awt.Color(255, 255, 255));
        jSeparator2.setPreferredSize(new java.awt.Dimension(420, 10));

        exDate_result1.setFont(new java.awt.Font("Segoe UI", 0, 24)); // NOI18N
        exDate_result1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        exDate_result1.setText("Expire Date:");

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                .addGap(538, 538, 538)
                .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(barcode_img1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(barcode_lbl1, javax.swing.GroupLayout.DEFAULT_SIZE, 481, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGap(25, 25, 25)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(ItemPriceVat_resukt1, javax.swing.GroupLayout.PREFERRED_SIZE, 445, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addComponent(exDate_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 451, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGroup(jPanel3Layout.createSequentialGroup()
                            .addComponent(ItemNum_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 197, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addComponent(ItemName_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 221, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGap(21, 21, 21))))
                .addGap(0, 0, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(ItemNum_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(ItemName_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(ItemPriceVat_resukt1, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(exDate_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(barcode_img1, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(barcode_lbl1, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(91, 91, 91)
                .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jButton2.setText("Print");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(28, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 510, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, 493, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(41, 41, 41))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(39, 39, 39)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, 298, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 55, Short.MAX_VALUE)
                .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(30, 30, 30))
        );

        pack();
    }// </editor-fold>    
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(new Printable() {
            @Override
            public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
                if (pageIndex > 0) {
                    return Printable.NO_SUCH_PAGE;
                }
                Graphics2D g2 = (Graphics2D) graphics;
                g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
                double scaleFactor = calculateScaleFactor(pageFormat);
                g2.scale(scaleFactor, scaleFactor);
                jPanel3.printAll(g2);

                return Printable.PAGE_EXISTS;
            }
        });
        boolean ok = job.printDialog();
        if (ok) {
            try {
                PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
                aset.add(OrientationRequested.PORTRAIT);
                aset.add(MediaSize.findMedia(2, 1, Size2DSyntax.INCH));
                job.print(aset);
                dispose();
            } catch (PrinterException ex) {
                JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }                                        
    private double calculateScaleFactor(PageFormat pageFormat) {
        // Calculate the scale factor to fit the panel to the paper size
        double panelWidth = jPanel3.getWidth();
        double panelHeight = jPanel3.getHeight();
        double paperWidth = pageFormat.getImageableWidth();
        double paperHeight = pageFormat.getImageableHeight();
        double scaleX = paperWidth / panelWidth;
        double scaleY = paperHeight / panelHeight;
        return Math.min(scaleX, scaleY);
    }
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new PrintView().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify                     
    private javax.swing.JLabel ItemName_result1;
    private javax.swing.JLabel ItemNum_result1;
    private javax.swing.JLabel ItemPriceVat_resukt1;
    private javax.swing.JLabel barcode_img1;
    private javax.swing.JLabel barcode_lbl1;
    private javax.swing.JLabel exDate_result1;
    private javax.swing.JButton jButton2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JSeparator jSeparator2;
    // End of variables declaration                   
}

and this is how I add get the image and display it on barcode_img.setIcon()

   public void displayData(int id) {
    Item item = DB_connection.getSelectedRow(id);
    ItemNum_result.setText(item.getItemNumber());
    ItemName_result.setText(item.getItemName());
    ItemPriceVat_resukt.setText("SR: " + item.getPrice() + "");
    barcode_lbl.setText(item.getBarcode());
    if (item.getExpireDate() != null) {
        exDate_result.setText("EX Date: " + item.getExpireDate());
    } else {
        exDate_result.setVisible(false);
    }
    if (!item.getBarcode().isEmpty() && !item.getBarcodeImagePath().isEmpty()) {
        Path path = Paths.get(item.getBarcodeImagePath());
        if (Files.exists(path)) {
            BufferedImage myPicture;
            try {
                myPicture = ImageIO.read(path.toFile());
                barcode_lbl.setText(item.getBarcode());
                barcode_img.setIcon(getImageScaled(myPicture, barcode_img));
                //barcode_img.setIcon(new ImageIcon(myPicture));
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
}

private Icon getImageScaled(BufferedImage myPicture, JLabel barcode_img1) {

    Image dimg = myPicture.getScaledInstance(barcode_img1.getWidth(), barcode_img1.getHeight(), Image.SCALE_SMOOTH);
    ImageIcon scaledImage = new ImageIcon(dimg);
    return scaledImage;
}

Print result
each paper have different size, so how make the jPanel scalable to fill all paper sizes ?
enter image description here
enter image description here

1

There are 1 best solutions below

0
MadProgrammer On

This is all going to be a little bit of overkill, but remember, Swing tends to operating on an assumption of 72dpi for screen and rendering, this is important, as it can really mess with you otherwise.

I some situations, you may be required to upscale the values to support 300dpi (assuming your printer is capable of this), but, that's another issue entirely. Also remember, it's been a VERY long time since I've needed to do this and would generally make use of things like JasperReports instead.

The "model"...

Let's start by decoupling somethings. The information you want to print should be represented by some kind of model, this allows you to decouple the data from the output (ie screen or printer). It also means you could change these rendering pipelines down the track without adversely effecting the other workflows.

public interface ItemModel {
    public String getName();
    public String getNumber();
    public double getPrice(); // Realsitically probably should be a long
    public LocalDate getExpireDate();
    public String getBarCodeValue();
}

public class DefaultItemModel implements ItemModel {

    private String name;
    private String number;
    private double price;
    private LocalDate expireDate;
    private String barCodeValue;

    public DefaultItemModel(String name, String number, double price, LocalDate expireDate, String barCodeValue) {
        this.name = name;
        this.number = number;
        this.price = price;
        this.expireDate = expireDate;
        this.barCodeValue = barCodeValue;
    }

    public String getName() {
        return name;
    }

    public String getNumber() {
        return number;
    }

    public double getPrice() {
        return price;
    }

    public LocalDate getExpireDate() {
        return expireDate;
    }

    public String getBarCodeValue() {
        return barCodeValue;
    }
}

The "helper"...

A general utility, this is mostly used to covert from inches to pixels based on a desired DPI.

public class PrintUtilities {
    // The number of CMs per Inch
    public static final double CM_PER_INCH = 0.393700787d;
    // The number of Inches per CMs
    public static final double INCH_PER_CM = 2.545d;
    // The number of Inches per mm's
    public static final double INCH_PER_MM = 25.45d;

    /**
     * Converts the given pixels to cm's based on the supplied DPI
     *
     * @param pixels
     * @param dpi
     * @return
     */
    public static double pixelsToCms(double pixels, double dpi) {
        return inchesToCms(pixels / dpi);
    }

    /**
     * Converts the given cm's to pixels based on the supplied DPI
     *
     * @param cms
     * @param dpi
     * @return
     */
    public static double cmsToPixel(double cms, double dpi) {
        return cmToInches(cms) * dpi;
    }

    public static double inchesToPixels(double inches, double dpi) {
        return inches * dpi;
    }

    /**
     * Converts the given cm's to inches
     *
     * @param cms
     * @return
     */
    public static double cmToInches(double cms) {
        return cms * CM_PER_INCH;
    }

    /**
     * Converts the given inches to cm's
     *
     * @param inch
     * @return
     */
    public static double inchesToCms(double inch) {
        return inch * INCH_PER_CM;
    }
}

The "view"...

The item view...

public class ItemView extends JPanel {
    private ItemModel itemModel;

    private JLabel itemName;
    private JLabel itemNumber;
    private JLabel price;
    private JLabel expireDate;
    private JLabel barCode;
    private JLabel barCodeNumber;

    protected static final double ratio = 0.6;

    public ItemView(ItemModel itemModel) throws IOException {
        this.itemModel = itemModel;

        setBackground(Color.WHITE);

        Font font36 = new Font("Segoe UI", 0, 36);
        Font font24 = new Font("Segoe UI", Font.BOLD, 24);

        itemName = new JLabel(itemModel.getName());
        itemName.setFont(font36);

        itemNumber = new JLabel(itemModel.getNumber());
        itemNumber.setFont(font36);

        price = new JLabel(NumberFormat.getCurrencyInstance().format(itemModel.getPrice()));
        price.setFont(font36);

        expireDate = new JLabel(DateTimeFormatter.ISO_LOCAL_DATE.format(itemModel.getExpireDate()));
        expireDate.setFont(font24);

        // Generate the bar code image
        barCode = new JLabel(new ImageIcon(generateBarCode(itemModel.getBarCodeValue())));

        barCodeNumber = new JLabel(itemModel.getBarCodeValue());
        barCodeNumber.setFont(font24);
        barCodeNumber.setHorizontalAlignment(JLabel.LEADING);

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(4, 4, 4, 4);
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0.5;

        add(itemName, gbc);
        gbc.gridx++;
        add(itemNumber, gbc);

        gbc.gridy++;
        gbc.gridx = 0;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        add(price, gbc);

        gbc.gridy++;
        add(expireDate, gbc);

        gbc.gridy++;
        gbc.weighty = 1;
        add(barCode, gbc);

        gbc.gridy++;
        gbc.weighty = 0;
        gbc.anchor = GridBagConstraints.LINE_START;
        add(barCodeNumber, gbc);
    }

    protected static BufferedImage generateBarCode(String barcodeValue) throws IOException {
        // Generate your bar code image
        return ImageIO.read(ItemView.class.getResource("/resources/images/BarCode.png"));
    }

    @Override
    public Dimension getPreferredSize() {
                    return new Dimension(
                            (int) PrintUtilities.inchesToPixels(6, 72),
                            (int) PrintUtilities.inchesToPixels(4, 72)
                    );
    }

}

This is a view used to represent the model. It was much simpler to create this then to try and decouple your existing code. As a side note, stop relying on the form editors, they aren't helping you.

The Printable...

I decoupled the Printable from the view for a number of reasons. You really don't want to be printing components which are on the screen, as you will need to change their size and position for printing, and this can have adverse issues when the component is live on the screen and it also demonstrates the possibility of using a different rendering approach when printing.

public class PrinterAction implements Printable {
    private ItemView itemView;

    public PrinterAction(ItemModel itemModel) throws IOException {
        this.itemView = new ItemView(itemModel);
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
        if (pageIndex > 0) {
            return Printable.NO_SUCH_PAGE;
        }

        double targetWidth = pageFormat.getImageableWidth();
        double targetHeight = pageFormat.getImageableHeight();

        Graphics2D g2 = (Graphics2D) graphics;
        g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
        itemView.setSize((int) targetWidth, (int) targetHeight);
        itemView.doLayout();
        itemView.printAll(g2);
        g2.setColor(Color.RED);
        g2.drawRect(0, 0, (int)targetWidth - 1, (int)targetHeight - 1);

        return Printable.PAGE_EXISTS;
    }
}

The "preview"...

This is a simple component which shows the item view and print action to the user. I've modified your original code in order to be able to make use of PDF rendering on the Mac, so you could give it a shot and see if it works as is and then test your workflow as well.

public class PrintView extends JPanel {

    private ItemModel itemModel;

    public PrintView(ItemModel itemModel) throws IOException {
        this.itemModel = itemModel;
        setLayout(new BorderLayout());

        add(new ItemView(itemModel));

        JButton print = new JButton("Print");
        print.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    // I've set up the Paper and PageFormat ahead of time
                    // as it's the only way I can get PDF rendering to work
                    // I'm assuming that's a 4"x6" varient, but you're
                    // printing in landscape - these are all assumptions
                    // based on some Googling.
                    // You may not need to do this, but it's the only way
                    // I was able to get PDF printing to work.
                    Paper paper = new Paper();
                    paper.setImageableArea(
                            0,
                            0,
                            PrintUtilities.inchesToPixels(4, 72),
                            PrintUtilities.inchesToPixels(6, 72)
                    );
                    PageFormat pf = new PageFormat();
                    pf.setPaper(paper);
                    pf.setOrientation(PageFormat.LANDSCAPE);

                    PrinterJob job = PrinterJob.getPrinterJob();
                    job.setPrintable(new PrinterAction(itemModel), pf);
//                        job.setPrintable(new PrinterAction(itemModel));
                    boolean ok = job.printDialog();
                    if (ok) {
//                            try {
//                                PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
//                                aset.add(OrientationRequested.PORTRAIT);
//                                aset.add(MediaSize.findMedia(6, 4, Size2DSyntax.INCH));
//                                job.print(aset);
//                            } catch (PrinterException ex) {
//                                JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
//                            }
                        try {
                            job.print();
                        } catch (PrinterException ex) {
                            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                    JOptionPane.showMessageDialog(PrintView.this, "Failed to start print job", "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        add(print, BorderLayout.SOUTH);
    }

}

Final output...

enter image description here

Just as a reference, the "printed" image is 5.94"x3.93" / 1782x1179 pixels @ 300dpi

Screen on the left, "printer" output on the right (I printed it directly to PDF to save on paper).