ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

java调用打印机,自定义模板

2026/9/14 20:07:47 拓冰建站 浏览量
java调用打印机,自定义模板

 前言😊

只要你能看懂中文就会用,直接CV直接改,讲究的就是CV大法的魅力!!!

 

 须知🐱‍👤

我们需要了解图像尺寸和物理尺寸之间的转换关系。

在图像处理中,通常使用像素作为图像的尺寸单位。
而像素和物理尺寸之间通常有一个固定的转换关系,这个关系取决于DPI(每英寸点数)。
在这个问题中,DPI是72,这意味着1英寸等于72像素。

因此,我们可以使用以下公式来进行换算:
图像尺寸(像素) = 物理尺寸(毫米) × (DPI / 25.4)

其中,25.4是1英寸的毫米数。

A4纸的尺寸为210mm×297mm,世界上多数国家所使用的纸张尺寸都是采用这一国际标准.

所以210x297mm的尺寸换算成72的图像尺寸的计算结果为:图像的宽度是 595.28 像素,高度是 841.89 像素。


效果展示🤣

预览效果👀

 打印效果💖


 代码🐱‍🐉

系统属性🎂

import java.awt.*;public final class SystemProperties {public static final double SCREEN_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().getWidth();public static final double SCREEN_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().getHeight();public static final String USER_DIR = System.getProperty("user.dir");public static final String USER_HOME = System.getProperty("user.home");public static final String USER_NAME = System.getProperty("user.name");public static final String FILE_SEPARATOR = System.getProperty("file.separator");public static final String LINE_SEPARATOR = System.getProperty("line.separator");public static final String PATH_SEPARATOR = System.getProperty("path.separator");public static final String JAVA_HOME = System.getProperty("java.home");public static final String JAVA_VENDOR = System.getProperty("java.vendor");public static final String JAVA_VENDOR_URL = System.getProperty("java.vendor.url");public static final String JAVA_VERSION = System.getProperty("java.version");public static final String JAVA_CLASS_PATH = System.getProperty("java.class.path");public static final String JAVA_CLASS_VERSION = System.getProperty("java.class.version");public static final String OS_NAME = System.getProperty("os.name");public static final String OS_ARCH = System.getProperty("os.arch");public static final String OS_VERSION = System.getProperty("os.version");public static final String[] FONT_NAME_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();public static final Font[] FONT_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();public SystemProperties() {}
}

 预览弹窗👀

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;public class PrintPreviewDialog extends JDialogimplements ActionListener {private JButton nextButton = new JButton("下一个");private JButton previousButton = new JButton("以前");private JButton closeButton = new JButton("关闭");private JPanel buttonPanel = new JPanel();private PreviewCanvas canvas;public PrintPreviewDialog(Frame parent, String title, boolean modal, PrintHelp pt, String str) {super(parent, title, modal);canvas = new PreviewCanvas(pt, str);setLayout();}private void setLayout() {this.getContentPane().setLayout(new BorderLayout());this.getContentPane().add(canvas, BorderLayout.CENTER);nextButton.setMnemonic('N');nextButton.addActionListener(this);buttonPanel.add(nextButton);previousButton.setMnemonic('N');previousButton.addActionListener(this);buttonPanel.add(previousButton);closeButton.setMnemonic('N');closeButton.addActionListener(this);buttonPanel.add(closeButton);this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);// 弹窗xy位置,宽高this.setBounds((int) ((SystemProperties.SCREEN_WIDTH - 400) / 2), (int) ((SystemProperties.SCREEN_HEIGHT - 400) / 2), 2360, 1180);}public void actionPerformed(ActionEvent evt) {Object src = evt.getSource();if (src == nextButton)nextAction();else if (src == previousButton)previousAction();else if (src == closeButton)closeAction();}private void closeAction() {this.setVisible(false);this.dispose();}private void nextAction() {canvas.viewPage(1);}private void previousAction() {canvas.viewPage(-1);}class PreviewCanvas extends JPanel {private String printStr;private int currentPage = 0;private PrintHelp preview;public PreviewCanvas(PrintHelp pt, String str) {printStr = str;preview = pt;}public void paintComponent(Graphics g) {super.paintComponent(g);Graphics2D g2 = (Graphics2D) g;PageFormat pf = PrinterJob.getPrinterJob().defaultPage();double xoff;double yoff;double scale;double px = pf.getWidth();double py = pf.getHeight();double sx = getWidth() - 1;double sy = getHeight() - 1;if (px / py < sx / sy) {scale = sy / py;xoff = 0.5 * (sx - scale * px);yoff = 0;} else {scale = sx / px;xoff = 0;yoff = 0.5 * (sy - scale * py);}g2.translate((float) xoff, (float) yoff);g2.scale((float) scale, (float) scale);// 白板xy轴位置,宽高Rectangle2D page = new Rectangle2D.Double(0, 0, px, py);g2.setPaint(Color.white);g2.fill(page);g2.setPaint(Color.black);g2.draw(page);try {preview.print(g2, pf, currentPage);} catch (PrinterException pe) {g2.draw(new Line2D.Double(0, 0, px, py));g2.draw(new Line2D.Double(0, px, 0, py));}}public void viewPage(int pos) {int newPage = currentPage + pos;if (0 <= newPage && newPage < preview.getPagesCount(printStr)) {currentPage = newPage;repaint();}}}
}

打印模板🐱‍👤

import com.scwl.printer_jg.model.GoodsDTO;
import com.scwl.printer_jg.model.WeighingListDTO;import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.*;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Properties;/*** @author 小影* @create 2023-12-22 17:05* @describe: JFrame:Java图形化界面设计——容器* java.awt.print.Printable动作事件监听器* java.awt.print.Printable:通用的打印 API 提供类和接口*/
public class PrintHelp extends JFrame implements ActionListener, Printable {public PrintHelp() {this.setTitle("小影打印测试");// 窗口标题this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setBounds((int) ((SystemProperties.SCREEN_WIDTH - 800) / 2), (int) ((SystemProperties.SCREEN_HEIGHT - 600) / 2), 800, 600);initLayout();}private WeighingListDTO weighingListDTO;// 参数实体类private int PAGES = 0;private JTextArea area = new JTextArea();// 用来创建一个默认的文本域private JPanel buttonPanel = new JPanel();// 创建面板private JScrollPane scroll = new JScrollPane(area);// 创建窗口private String printStr;private JButton printTextButton = new JButton("打印测试");private JButton previewButton = new JButton("打印预览");private JButton printText2Button = new JButton("打印测试2");private JButton printFileButton = new JButton("打印文件");private JButton printFrameButton = new JButton("Print Frame");private JButton exitButton = new JButton("退出");public static void main(String[] args) throws PrinterException {Book book = new Book();PageFormat pf = new PageFormat();pf.setOrientation(PageFormat.PORTRAIT);Paper p = new Paper();p.setSize(595, 283);// 纸张大小单位是像素p.setImageableArea(1, 5, 590, 282);// A4(595 X 842)设置打印区域,其�?0�?0应该�?72�?72,因为A4纸的默认X,Y边距�?72pf.setPaper(p);WeighingListDTO datas = new WeighingListDTO();datas.setUnitName("XXXXX有限公司称重计量单");datas.setClientName("客户名称: XXXXX里科技有限公司");datas.setPlateNumber("闽C:66666");datas.setOrderNo("过磅单:GB88888888");datas.setSjName("司机签名:");datas.setSjPhone("司机电话:");datas.setYssl("一式三联");ArrayList<GoodsDTO> goodList = new ArrayList<>();GoodsDTO goods = new GoodsDTO();GoodsDTO goods2 = new GoodsDTO();goods.setGoodsName("物料名称");goods.setNumber("件数");goods.setTare("皮重");goods.setGrossWeight("毛重");goods.setSuttle("净重");goods.setCSuttle("纯净重");goods.setQingTime("轻磅时间");goods.setZhongTime("重磅时间");goods2.setGoodsName("皂角");goods2.setNumber("100");goods2.setTare("15.76");goods2.setGrossWeight("49.80");goods2.setSuttle("34.0400");goods2.setCSuttle("34.0400");goods2.setQingTime("2023/12/22 09:30:00");goods2.setZhongTime("2023/12/22 10:30:00");goodList.add(goods);goodList.add(goods2);datas.setList(goodList);PrintHelp printHelp = new PrintHelp();printHelp.init(datas);book.append(printHelp, pf);PrinterJob job = PrinterJob.getPrinterJob();job.setPageable(book);// job.print();//进行打印printHelp.setVisible(true); // 打印窗口}public void init(WeighingListDTO datas) {this.weighingListDTO = datas;}private void initLayout() {this.getContentPane().setLayout(new BorderLayout());this.getContentPane().add(scroll, BorderLayout.CENTER);printTextButton.setMnemonic('P');printTextButton.addActionListener(this);buttonPanel.add(printTextButton);previewButton.setMnemonic('v');previewButton.addActionListener(this);buttonPanel.add(previewButton);printText2Button.setMnemonic('e');printText2Button.addActionListener(this);buttonPanel.add(printText2Button);printFileButton.setMnemonic('i');printFileButton.addActionListener(this);buttonPanel.add(printFileButton);printFrameButton.setMnemonic('F');printFrameButton.addActionListener(this);buttonPanel.add(printFrameButton);exitButton.setMnemonic('x');exitButton.addActionListener(this);buttonPanel.add(exitButton);this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);}/*** 监听按钮** @param evt*/public void actionPerformed(ActionEvent evt) {Object src = evt.getSource();if (src == printTextButton)printTextAction();else if (src == previewButton)previewAction();else if (src == printText2Button)printText2Action();else if (src == printFileButton)printFileAction();else if (src == printFrameButton)printFrameAction();else if (src == exitButton)exitApp();}/*** 打印测试*/private void printTextAction() {printStr = area.getText().trim();if (printStr != null && printStr.length() > 0) {PAGES = getPagesCount(printStr);PrinterJob myPrtJob = PrinterJob.getPrinterJob();PageFormat pageFormat = myPrtJob.defaultPage();myPrtJob.setPrintable(this, pageFormat);if (myPrtJob.printDialog()) {try {myPrtJob.print();} catch (PrinterException pe) {pe.printStackTrace();}}} else {// 需要输入内容JOptionPane.showConfirmDialog(null, "对不起,打印作业为空,打印取消!", "提示", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);}}/*** 打印预览*/private void previewAction() {printStr = area.getText().trim();PAGES = getPagesCount(printStr);(new PrintPreviewDialog(this, "打印预览", true, this, printStr)).setVisible(true);}private void printText2Action() {printStr = area.getText().trim();if (printStr != null && printStr.length() > 0) {PAGES = getPagesCount(printStr);DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;PrintService printService = PrintServiceLookup.lookupDefaultPrintService();DocPrintJob job = printService.createPrintJob();PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();DocAttributeSet das = new HashDocAttributeSet();Doc doc = new SimpleDoc(this, flavor, das);try {job.print(doc, pras);} catch (PrintException pe) {pe.printStackTrace();}} else {JOptionPane.showConfirmDialog(null, "Sorry, Printer Job is Empty, Print Cancelled!", "Empty", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);}}private void printFileAction() {JFileChooser fileChooser = new JFileChooser(SystemProperties.USER_DIR);int state = fileChooser.showOpenDialog(this);if (state == fileChooser.APPROVE_OPTION) {File file = fileChooser.getSelectedFile();PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();PrintService service = ServiceUI.printDialog(null, 200, 200, printService, defaultService, flavor, pras);if (service != null) {try {DocPrintJob job = service.createPrintJob();FileInputStream fis = new FileInputStream(file);DocAttributeSet das = new HashDocAttributeSet();Doc doc = new SimpleDoc(fis, flavor, das);job.print(doc, pras);} catch (Exception e) {e.printStackTrace();}}}}private void printFrameAction() {Toolkit kit = Toolkit.getDefaultToolkit();Properties props = new Properties();props.put("awt.print.printer", "durango");props.put("awt.print.numCopies", "2");if (kit != null) {PrintJob printJob = kit.getPrintJob(this, "Print Frame", props);if (printJob != null) {Graphics pg = printJob.getGraphics();if (pg != null) {try {this.printAll(pg);} finally {pg.dispose();}}printJob.end();}}}/*** 退出*/private void exitApp() {this.setVisible(false);this.dispose();System.exit(0);}/*** 获取页数数量** @param curStr* @return*/public int getPagesCount(String curStr) {int page = 0;int position, count = 0;String str = curStr;while (str.length() > 0) {position = str.indexOf('\n');count += 1;if (position != -1)str = str.substring(position + 1);elsestr = "";}if (count > 0)page = count / 54 + 1;return page;}/*** 打印模板** @param g    将页面绘制到其中的上下文* @param pf   正在绘制的页面的大小和方向* @param page 要绘制的页的从零开始的索引* @return* @throws PrinterException*/@Overridepublic int print(Graphics g, PageFormat pf, int page) throws PrinterException {// 转换成Graphics2DGraphics2D g2 = (Graphics2D) g;// 设置打印颜色为黑// 抗锯齿就是减少图形边缘的锯齿状像素格,使画面看上去更精细而不是满屏的马赛克g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g2.setColor(Color.black);// 黑色// 打印起点坐标 对象的可成像区域左上方点的x 坐标 和左上的y坐标double x = pf.getImageableX();// 返回与此 PageFormat 相关 Paperdouble y = pf.getImageableY();switch (page) {case 0:// 新建 个打印字体样式(1.字体名称 2.样式(加粗).3字号大小Font font = new Font("微软雅黑", Font.PLAIN, 16);// 给g2设置字体g2.setFont(font);// 保存虚线的宽float[] dash1 = {2.0f};// 设置打印线的属 1.线宽 2 3、不知道 4、空白的宽度 5、虚线的宽度 6、偏移量g2.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 2.0f, dash1, 0.0f));float fontHeigth1 = font.getSize2D();// 字体大小// 左上40起点  中间160  右边400起点// 240高起点// 标题 (渲染的值,X轴,Y轴)g2.drawString(weighingListDTO.getUnitName(), 220, 40);// 如果把握不好尺寸就打印(g2.drawString(weighingListDTO.getUnitName() + "2", 50, 20);),然后再自己慢慢推敲出来想要的位置// g2.drawString(weighingListDTO.getUnitName() + "2", 50, 20);// g2.drawString(weighingListDTO.getUnitName() + "3", 60, 40);// g2.drawString(weighingListDTO.getUnitName() + "4", 70, 60);// g2.drawString(weighingListDTO.getUnitName() + "5", 80, 80);// g2.drawString(weighingListDTO.getUnitName() + "6", 90, 100);// g2.drawString(weighingListDTO.getUnitName() + "7", 100, 120);// g2.drawString(weighingListDTO.getUnitName() + "8", 110, 140);// g2.drawString(weighingListDTO.getUnitName() + "9", 120, 160);// g2.drawString(weighingListDTO.getUnitName() + "11", 130, 180);// g2.drawString(weighingListDTO.getUnitName() + "12", 140, 200);// g2.drawString(weighingListDTO.getUnitName() + "13", 150, 220);// g2.drawString(weighingListDTO.getUnitName() + "14", 160, 240);// g2.drawString(weighingListDTO.getUnitName() + "15", 170, 260);// 新建个字体Font font2 = new Font("微软雅黑", Font.PLAIN, 10);g2.setFont(font2);// 设置字体g2.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 2.0f, dash1, 0.0f));float fontHeigth2 = (int) font.getSize2D();// 字体2的高int tempHeight = (int) (fontHeigth1 * 2 + 50);// 临时高。字体1的高2倍 +50Integer hang_juInteger = 15;// 行距g2.drawString(weighingListDTO.getClientName(), 40, 60); 客户/供应商g2.drawString(weighingListDTO.getPlateNumber(), 250, 60);// 车牌号g2.drawString(weighingListDTO.getOrderNo(), 440, 60);// 磅单号int listY = 80;for (GoodsDTO dto : weighingListDTO.getList()) {// 物料名称g2.drawString(dto.getGoodsName(), 40, listY);// 件数g2.drawString(dto.getNumber(), 90,listY);// 皮重g2.drawString(dto.getTare(), 130,listY);// 毛重g2.drawString(dto.getGrossWeight(), 170,listY);// 净重g2.drawString(dto.getSuttle(), 210,listY);// 纯净重g2.drawString(dto.getSuttle(), 250,listY);// 轻榜时间g2.drawString(dto.getQingTime(), 320,listY);// 重磅时间g2.drawString(dto.getZhongTime(), 430,listY);listY += 20;// 每行间距20像素}// 司机签名g2.drawString(weighingListDTO.getSjName(), 40,230);// // 司机电话g2.drawString(weighingListDTO.getSjPhone(), 160,230 );// // 一式三联g2.drawString(weighingListDTO.getYssl(), 500, 230);return PAGE_EXISTS;default:return NO_SUCH_PAGE;}}}

注意:💖

如果要改成接口触发打印就需要改一下启动类,否则会报错:java.awt.HeadlessException: null

@SpringBootApplication
public class PrinterJgApplication {public static void main(String[] args) {SpringApplicationBuilder builder = new SpringApplicationBuilder(PrinterJgApplication.class);builder.headless(false).run(args);}
}