📄 java打印程序设计.txt
字号:
private void printText2Action() { printFlag = 0; //打印标志清零 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); } }
3.2 打印预览
3.2.1应用场景
大多少商业应用都需要提供打印预览机制,它可以让我们在屏幕上看到页面,这样就不会因为不喜欢的打印结果而浪费纸张。假设我们在打印上一节所说的文本之前,需要先进行打印预览。那么该怎么实现呢?
界面实现图示如下:(Next预览下一页,Preview预览前一页,Close则关闭预览)
3.2.2解决方法
基本思路:虽然Java2平台的打印API并不提供标准的打印预览对话框,但是自己来进行设计也并不复杂。正常情况下,print方法将页面环境绘制到一个打印机图形环境上,从而实现打印。而事实上,print方法并不能真正产生打印页面,它只是将待打印内容绘制到图形环境上。所以,我们可以忽略掉屏幕图形环境,经过适当的缩放比例,使整个打印页容纳在一个屏幕矩形里,从而实现精确的打印预览。
在打印预览的设计实现中,主要需要解决两个问题。第一,如何将打印内容按合适的比例绘制到屏幕;第二,如何实现前后翻页。下面我给出这两个问题的具体实现方法,完整的实现请参看附件中的PrintPreviewDialog.java文件。
/*将待打印内容按比例绘制到屏幕*/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); 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(); } }
这样,在按下"Next"按钮时,只需要调用canvas.viewPage(1);而在按下"Preview"按钮时,只需要调用canvas.viewPage(-1)即可实现预览的前后翻页。
3.3 打印图形
3.3.1应用场景
在实际应用中,我们还需要打印图形。譬如,我们有时需要将一个Java Applet的完整界面或一个应用程序窗体及其所包含的全部组件都打印出来,又应该如何实现呢?
3.3.2解决方法
基本思路如下:在Java的Component类及其派生类中都提供了print和printAll方法,只要设置好属性就可以直接调用这两个方法,从而实现对组件及图形的打印。
/*打印指定的窗体及其包含的组件*/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();//结束打印作业 } }}
3.4 打印文件
3.4.1应用场景
在很多实际应用情况下,我们可能都需要打印用户指定的某一个文件。该文件可能是图形文件,如GIF、JPEG等等;也可能是文本文件,如TXT、Java文件等等;还可能是复杂的PDF、DOC文件等等。那么对于这样的打印需求,我们又应该如何实现呢?
3.4.2解决方法
基本思路:在jdk1.4以前的版本,要实现这样的打印功能将非常麻烦和复杂,甚至是难以想象的。但幸运的是,jdk1.4的打印服务API提供了一整套的打印文件流的类和方法。利用它们,我们可以非常方便快捷地实现各式各样不同类型文件的打印功能。下面给出一个通用的处理方法。
/*打印指定的文件*/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(); //设置打印格式,因为未确定文件类型,这里选择AUTOSENSE 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(); } } }}
在上面的示例中,因尚未确定文件的类型,所以将指定文件的打印格式定义为DocFlavor.INPUT_STREAM.AUTOSENSE。事实上,如果在进行打印之前,就已确定地知道文件的格式,如为GIF,就应定义为DocFlavor.INPUT_STREAM.GIF ;如为PDF,就应该定义为DocFlavor.INPUT_STREAM.PDF;如为纯ASCII文件,就可以定义为 DocFlavor.INPUT_STREAM.TEXT_HTML_US_ASCII。等等。jdk1.4的javax.print.DocFlavor提供了极为丰富的文件流类型,你可以根据具体的应用需求进行合适的选择。具体的API参考文档可见本文的参考资料3。
4 结束语
以上是本人在两年多J2EE应用开发中,总结的关于用Java进行打印程序设计的一些经验,希望能给大家一些启示和裨益。尽管目前用Java来实现打印功能与用Microsoft的MFC API相比确实有更多的麻烦。但jdk1.4的推出,对Java以前较弱的打印功能是一个极好的补充。相信大家如果能够很好地理解前文所述的打印程序设计实例,并加以应用和拓展,应该可以解决目前大部分应用的实际编程问题。而随着Java的进一步发展和完善,必将更好地充实其基础类库及打印API,相信用Java实现高级打印功能也将越来越不成为我们这些Java痴迷者头痛的问题。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -