打印一半面板

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

晚上好,堆栈溢出,

我正在尝试在“zebra gk420t”打印机上打印 Jpanel,但是当我给它下订单时,它只打印面板的一半,如图所示。

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                   
}

这就是我添加获取图像并将其显示在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;
}

打印结果
每张纸张都有不同的尺寸,那么如何让jPanel可扩展以填充所有纸张尺寸呢?

java swing printing jpanel zebra-printers
1个回答
0
投票

这一切都有点矫枉过正,但请记住,Swing 倾向于在屏幕和渲染的 72dpi 假设上运行,这一点很重要,否则它真的会让您感到困惑。

在某些情况下,您可能需要升级这些值以支持 300dpi(假设您的打印机能够做到这一点),但是,这完全是另一个问题。还要记住,自从我需要这样做以来已经很长一段时间了,并且通常会使用 JasperReports 之类的东西来代替。

“模型”...

让我们从解耦开始。您想要打印的信息应该由某种模型表示,这允许您将数据与输出(即屏幕或打印机)解耦。这还意味着您可以沿着轨道更改这些渲染管道,而不会对其他工作流程产生不利影响。

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;
    }
}

“帮手”...

一个通用实用程序,主要用于根据所需的 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;
    }
}

“景色”...

项目视图...

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)
                    );
    }

}

这是用于表示模型的视图。创建它然后尝试解耦现有代码要简单得多。附带说明一下,不要再依赖表单编辑器,它们对您没有帮助。

Printable
...

出于多种原因,我将

Printable
从视图中分离出来。您确实不想打印屏幕上的组件,因为您需要更改它们的尺寸和位置进行打印,当组件在屏幕上显示时,这可能会产生不利的问题,并且它还表明了以下可能性:打印时使用不同的渲染方法。

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;
    }
}

“预览”...

这是一个简单的组件,向用户显示项目视图和打印操作。我修改了您的原始代码,以便能够在 Mac 上使用 PDF 渲染,因此您可以尝试一下,看看它是否按原样工作,然后也测试您的工作流程。

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);
    }

}

最终输出...

仅供参考,“打印”图像为 5.94"x3.93" / 1782x1179 像素 @ 300dpi

左边是屏幕,右边是“打印机”输出(我直接打印成PDF保存在纸上)。

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