Java打印程序設(shè)計(jì)1_第1頁(yè)
Java打印程序設(shè)計(jì)1_第2頁(yè)
Java打印程序設(shè)計(jì)1_第3頁(yè)
Java打印程序設(shè)計(jì)1_第4頁(yè)
Java打印程序設(shè)計(jì)1_第5頁(yè)
已閱讀5頁(yè),還剩17頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第頁(yè)Java打印程序設(shè)計(jì)1

前言

在我們的實(shí)際工作中,經(jīng)常需要實(shí)現(xiàn)打印功能。但由于歷史原因,Java提供的打印功能一直都比擬弱。實(shí)際上最初的jdk根本不支持打印,直到j(luò)dk1.1才引入了很輕量的打印支持。所以,在以前用Java/Applet/JSP/Servlet設(shè)計(jì)的程序中,較復(fù)雜的打印都是通過調(diào)用ActiveX/OCX控件或者VB/VC程序來實(shí)現(xiàn)的,非常麻煩。實(shí)際上,SUN公司也一直致力于Java打印功能的完善,而Java2平臺(tái)那么終于有了一個(gè)強(qiáng)健的打印模式的開端,該打印模式與Java2D圖形包充分結(jié)合成一體。更令人鼓舞的是,新發(fā)布的jdk1.4那么提供了一套完整的"Java

打印效勞

API"

(Java

Print

Service

API),它對(duì)已有的打印功能是積極的補(bǔ)充。利用它,我們可以實(shí)現(xiàn)大局部實(shí)際應(yīng)用需求,包括打印文字、圖形、文件及打印預(yù)覽等等。本文將通過一個(gè)具體的程序?qū)嵗齺碚f明如何設(shè)計(jì)Java打印程序以實(shí)現(xiàn)這些功能,并對(duì)不同版本的實(shí)現(xiàn)方法進(jìn)展分析比擬,希望大家能從中獲取一些有益的提示。

2

Java中的打印

2.1

Java的打印API

Java的打印API主要存在于java.awt.print包中。而jdk1.4新增的類那么主要存在于javax.print包及其相應(yīng)的子包javax.print.event和javax.print.attribute中。其中javax.print包中主要包含打印效勞的相關(guān)類,而javax.print.event那么包含打印事件的相關(guān)定義,javax.print.attribute那么包括打印效勞的可用屬性列表等。

2.2

如何實(shí)現(xiàn)打印

要產(chǎn)生一個(gè)打印,至少需要考慮兩條:

需要一個(gè)打印效勞對(duì)象。這可通過三種方式實(shí)現(xiàn):在jdk1.4之前的版本,必須要實(shí)現(xiàn)java.awt.print.Printable接口或通過Toolkit.getDefaultToolkit().getPrintJob來獲取打印效勞對(duì)象;在jdk1.4中那么可以通過javax.print.PrintSerivceLookup來查找定位一個(gè)打印效勞對(duì)象。

需要開場(chǎng)一個(gè)打印工作。這也有幾種實(shí)現(xiàn)方法:在jdk1.4之前可以通過java.awt.print.PrintJob(jdk1.1提供的,現(xiàn)在已經(jīng)很少用了)調(diào)用print或printAll方法開場(chǎng)打印工作;也可以通過java.awt.print.PrinterJob的printDialog顯示打印對(duì)話框,然后通過print方法開場(chǎng)打?。辉趈dk1.4中那么可以通過javax.print.ServiceUI的printDialog顯示打印對(duì)話框,然后調(diào)用print方法開場(chǎng)一個(gè)打印工作。

2.3

打印機(jī)對(duì)話框

Printable的打印對(duì)話框

開場(chǎng)打印工作之前,可以通過PrinterJob.printDialog來顯示一個(gè)打印對(duì)話框。它給用戶一個(gè)時(shí)機(jī)以選擇應(yīng)該打印的頁(yè)碼范圍,并可供用戶改變打印設(shè)置。它是一個(gè)本地對(duì)話框。

事實(shí)上,當(dāng)從一個(gè)Printable對(duì)象進(jìn)展一個(gè)打印工作時(shí),打印對(duì)象并不知道需要打印多少頁(yè)。它只是不停地調(diào)用print方法。只要print方法返回Printable.PAGE_EXISTS值,打印工作就不停地產(chǎn)生打印頁(yè),直到print方法返回Printable.NO_SUCH_PAGE時(shí),打印工作才停頓。

由于打印工作只有在打印完成后才進(jìn)展準(zhǔn)確的頁(yè)數(shù)計(jì)算,所以在對(duì)話框上的頁(yè)碼范圍是尚未初始化的[1,9999]。我們可以通過構(gòu)建一個(gè)java.awt.print.Book對(duì)象傳遞給打印對(duì)象;也可以通過指定的格式計(jì)算需要打印的頁(yè)數(shù)并傳遞給打印對(duì)象,使其準(zhǔn)確地知道要打印多少頁(yè)。

2.3.2

ServiceUI的打印對(duì)話框

與Printable的對(duì)話框不同的是,在jdk1.4提供ServiceUI的打印機(jī)對(duì)話框的缺省行為已經(jīng)用新的

API

更改了:缺省情況下對(duì)話框不顯示。我們必須使用ServiceUI類調(diào)用printDialog方法創(chuàng)立如下所示的打印對(duì)話框。

3

Java打印程序設(shè)計(jì)實(shí)例

3.1

打印文本

3.1.1

應(yīng)用場(chǎng)景

假設(shè)我們需要打印一個(gè)窗體的某個(gè)文本編輯域(可能只有幾行,也可能包含多頁(yè))的內(nèi)容,并且每頁(yè)最多打印54行,如何實(shí)現(xiàn)呢?

3.1.2

解決方法

根本思路如下:首先我們需要實(shí)現(xiàn)Printable接口,然后按照每頁(yè)最多54行的格式計(jì)算共需要打印多少頁(yè),當(dāng)打印文本的按鈕被點(diǎn)擊時(shí),執(zhí)行相應(yīng)的打印動(dòng)作。打印文本的具體操作可通過Graphics2D的drawString方法來實(shí)現(xiàn)。

1、實(shí)現(xiàn)Printable接口

/*Graphic指明打印的圖形環(huán)境;PageFormat指明打印頁(yè)格式(頁(yè)面大小以點(diǎn)為計(jì)量單位,1點(diǎn)為1英寸的1/72,1英寸為25.4毫米。A4紙大致為595×842點(diǎn));page指明頁(yè)號(hào)*/

public

int

print(Graphics

g,

PageFormat

pf,

int

page)

throws

PrinterException

{

Graphics2D

g2

=

(Graphics2D)g;

g2.setPaint(Color.black);

//設(shè)置打印顏色為黑色

if

(page

>=

PAGES)

//當(dāng)打印頁(yè)號(hào)大于需要打印的總頁(yè)數(shù)時(shí),打印工作完畢

return

Printable.NO_SUCH_PAGE;

g2.translate(pf.getImageableX(),

pf.getImageableY());//轉(zhuǎn)換坐標(biāo),確定打印邊界

drawCurrentPageText(g2,

pf,

page);

//打印當(dāng)前頁(yè)文本

return

Printable.PAGE_EXISTS;

//存在打印頁(yè)時(shí),繼續(xù)打印工作

}

/*打印指定頁(yè)號(hào)的具體文本內(nèi)容*/

private

void

drawCurrentPageText(Graphics2D

g2,

PageFormat

pf,

int

page)

{

String

s

=

getDrawText(printStr)[page];

//獲取當(dāng)前頁(yè)的待打印文本內(nèi)容

//獲取默認(rèn)字體及相應(yīng)的尺寸

FontRenderContext

context

=

g2.getFontRenderContext();

Font

f

=

area.getFont();

String

drawText;

float

ascent

=

16;

//給定字符點(diǎn)陣

int

k,

i

=

f.getSize(),

lines

=

0;

while(s.length()

>

0

&&

lines

<

54)

//每頁(yè)限定在54行以內(nèi)

{

k

=

s.indexOf('\n');

//獲取每一個(gè)回車符的位置

if

(k

!=

-1)

//存在回車符

{

lines

+=

1;

//計(jì)算行數(shù)

drawText

=

s.substring(0,

k);

//獲取每一行文本

g2.drawString(drawText,

0,

ascent);

//具體打印每一行文本,同時(shí)走紙移位

if

(s.substring(k

+

1).length()

>

0)

{

s

=

s.substring(k

+

1);

//截取尚未打印的文本

ascent

+=

i;

}

}

else

//不存在回車符

{

lines

+=

1;

//計(jì)算行數(shù)

drawText

=

s;

//獲取每一行文本

g2.drawString(drawText,

0,

ascent);

//具體打印每一行文本,同時(shí)走紙移位

s

=

"";

//文本已完畢

}

}

}

/*將打印目標(biāo)文本按頁(yè)存放為字符串?dāng)?shù)組*/

public

String[]

getDrawText(String

s)

{

String[]

drawText

=

new

String[PAGES];

//根據(jù)頁(yè)數(shù)初始化數(shù)組

for

(int

i

=

0;

i

<

PAGES;

i++)

drawText[i]

=

"";

//數(shù)組元素初始化為空字符串

int

k,

suffix

=

0,

lines

=

0;

while

(s.length()

>

0)

{

if

(lines

<

54)

//不夠一頁(yè)時(shí)

{

k

=

s.indexOf('\n');

if

(k

!=

-1)

//存在回車符

{

lines

+=

1;

//行數(shù)累加

//計(jì)算該頁(yè)的具體文本內(nèi)容,存放到相應(yīng)下標(biāo)的數(shù)組元素

drawText[suffix]

=

drawText[suffix]

+

s.substring(0,

k

+

1);

if

(s.substring(k

+

1).length()

>

0)

s

=

s.substring(k

+

1);

}

else

{

lines

+=

1;

//行數(shù)累加

//將文本內(nèi)容存放到相應(yīng)的數(shù)組元素

drawText[suffix]

=

drawText[suffix]

+

s;

s

=

"";

}

}

else

//已滿一頁(yè)時(shí)

{

lines

=

0;

//行數(shù)統(tǒng)計(jì)清零

suffix++;

//數(shù)組下標(biāo)加1

}

}

return

drawText;

}

2、計(jì)算需要打印的總頁(yè)數(shù)

public

int

getPagesCount(String

curStr)

{

int

page

=

0;

int

position,

count

=

0;

String

str

=

curStr;

while(str.length()

>

0)

//文本尚未計(jì)算完畢

{

position

=

str.indexOf('\n');

//計(jì)算回車符的位置

count

+=

1;

//統(tǒng)計(jì)行數(shù)

if

(position

!=

-1)

str

=

str.substring(position

+

1);

//截取尚未計(jì)算的文本

else

str

=

"";

//文本已計(jì)算完畢

}

if

(count

>

0)

page

=

count

/

54

+

1;

//以總行數(shù)除以54獲取總頁(yè)數(shù)

return

page;

//返回需打印的總頁(yè)數(shù)

}

3.1、以jdk1.4以前的版本實(shí)現(xiàn)打印動(dòng)作按鈕監(jiān)聽,并完成具體的打印操作

private

void

printTextAction()

{

printStr

=

area.getText().trim();

//獲取需要打印的目標(biāo)文本

if

(printStr

!=

null

&&

printStr.length()

>

0)

//當(dāng)打印內(nèi)容不為空時(shí)

{

PAGES

=

getPagesCount(printStr);

//獲取打印總頁(yè)數(shù)

PrinterJob

myPrtJob

=

PrinterJob.getPrinterJob();

//獲取默認(rèn)打印作業(yè)

PageFormat

pageFormat

=

myPrtJob.defaultPage();

//獲取默認(rèn)打印頁(yè)面格式

myPrtJob.setPrintable(this,

pageFormat);

//設(shè)置打印工作

if

(myPrtJob.printDialog())

//顯示打印對(duì)話框

{

try

{

myPrtJob.print();

//進(jìn)展每一頁(yè)的具體打印操作

}

catch(PrinterException

pe)

{

pe.printStackTrace();

}

}

}

else

{

//如果打印內(nèi)容為空時(shí),提示用戶打印將取消

JOptionPane.showConfirmDialog(null,

"Sorry,

Printer

Job

is

Empty,

Print

Cancelled!",

"Empty",

JOptionPane.DEFAULT_OPTION,

JOptionPane.WARNING_MESSAGE);

}

}

3.2、以jdk1.4新版本提供的API實(shí)現(xiàn)打印動(dòng)作按鈕監(jiān)聽,并完成具體的打印操作

private

void

printText2Action()

{

printFlag

=

0;

//打印標(biāo)志清零

printStr

=

area.getText().trim();//獲取需要打印的目標(biāo)文本

if

(printStr

!=

null

&&

printStr.length()

>

0)

//當(dāng)打印內(nèi)容不為空時(shí)

{

PAGES

=

getPagesCount(printStr);

//獲取打印總頁(yè)數(shù)

//指定打印輸出格式

DocFlavor

flavor

=

DocFlavor.SERVICE_FORMATTED.PRINTABLE;

//定位默認(rèn)的打印效勞

PrintService

printService

=

PrintServiceLookup.lookupDefaultPrintService();

//創(chuàng)立打印作業(yè)

DocPrintJob

job

=

printService.createPrintJob();

//設(shè)置打印屬性

PrintRequestAttributeSet

pras

=

new

HashPrintRequestAttributeSet();

DocAttributeSet

das

=

new

HashDocAttributeSet();

//指定打印內(nèi)容

Doc

doc

=

new

SimpleDoc(this,

flavor,

das);

//不顯示打印對(duì)話框,直接進(jìn)展打印工作

try

{

job.print(doc,

pras);

//進(jìn)展每一頁(yè)的具體打印操作

}

catch(PrintException

pe)

{

pe.printStackTrace();

}

}

else

{

//如果打印內(nèi)容為空時(shí),提示用戶打印將取消

JOptionPane.showConfirmDialog(null,

"Sorry,

Printer

Job

is

Empty,

Print

Cancelled!",

"Empty",

JOptionPane.DEFAULT_OPTION,

JOptionPane.WARNING_MESSAGE);

}

}

3.2

打印預(yù)覽

3.2.1應(yīng)用場(chǎng)景

大多少商業(yè)應(yīng)用都需要提供打印預(yù)覽機(jī)制,它可以讓我們?cè)谄聊簧峡吹巾?yè)面,這樣就不會(huì)因?yàn)椴幌矚g的打印結(jié)果而浪費(fèi)紙張。假設(shè)我們?cè)诖蛴∩弦还?jié)所說的文本之前,需要先進(jìn)展打印預(yù)覽。那么該怎么實(shí)現(xiàn)呢?

界面實(shí)現(xiàn)圖示如下:(Next預(yù)覽下一頁(yè),Preview預(yù)覽前一頁(yè),Close那么關(guān)閉預(yù)覽)

3.2.2解決方法

根本思路:雖然Java2平臺(tái)的打印API并不提供標(biāo)準(zhǔn)的打印預(yù)覽對(duì)話框,但是自己來進(jìn)展設(shè)計(jì)也并不復(fù)雜。正常情況下,print方法將頁(yè)面環(huán)境繪制到一個(gè)打印機(jī)圖形環(huán)境上,從而實(shí)現(xiàn)打印。而事實(shí)上,print方法并不能真正產(chǎn)生打印頁(yè)面,它只是將待打印內(nèi)容繪制到圖形環(huán)境上。所以,我們可以忽略掉屏幕圖形環(huán)境,經(jīng)過適當(dāng)?shù)目s放比例,使整個(gè)打印頁(yè)容納在一個(gè)屏幕矩形里,從而實(shí)現(xiàn)準(zhǔn)確的打印預(yù)覽。

在打印預(yù)覽的設(shè)計(jì)實(shí)現(xiàn)中,主要需要解決兩個(gè)問題。

第一,如何將打印內(nèi)容按適宜的比例繪制到屏幕;

第二,如何實(shí)現(xiàn)前后翻頁(yè)。

下面我給出這兩個(gè)問題的具體實(shí)現(xiàn)方法,完整的實(shí)現(xiàn)請(qǐng)參看附件中的PrintPreviewDialog.java文件。

/*將待打印內(nèi)容按比例繪制到屏幕*/

public

void

paintComponent(Graphics

g)

{

super.paintComponent(g);

Graphics2D

g2

=

(Graphics2D)g;

PageFormat

pf

=

PrinterJob.getPrinterJob().defaultPage();

//獲取頁(yè)面格式

double

xoff;

//在屏幕上頁(yè)面初始位置的水平偏移

double

yoff;

//在屏幕上頁(yè)面初始位置的垂直偏移

double

scale;

//在屏幕上適合頁(yè)面的比例

double

px

=

pf.getWidth();

//頁(yè)面寬度

double

py

=

pf.getHeight();

//頁(yè)面高度

double

sx

=

getWidth()

-

1;

double

sy

=

getHeight()

-

1;

if

(px/py

<

sx/sy)

{

scale

=

sy

/

py;

//計(jì)算比例

xoff

=

0.5

*

(sx

-

scale

*

px);

//水平偏移量

yoff

=

0;

}

else

{

scale

=

sx

/

px;

//計(jì)算比例

xoff

=

0;

yoff

=

0.5

*

(sy

-

scale

*

py);

//垂直偏移量

}

g2.translate((float)xoff,

(float)yoff);

//轉(zhuǎn)換坐標(biāo)

g2.scale((float)scale,

(float)scale);

Rectangle2D

page

=

new

Rectangle2D.Double(0,

0,

px,

py);

//繪制頁(yè)面矩形

g2.setPaint(Color.white);

//設(shè)置頁(yè)面背景為白色

g2.fill(page);

g2.setPaint(Color.black);//設(shè)置頁(yè)面文字為黑色

g2.draw(page);

try

{

preview.print(g2,

pf,

currentPage);

//顯示指定的預(yù)覽頁(yè)面

}

catch(PrinterException

pe)

{

g2.draw(new

Line2D.Double(0,

0,

px,

py));

g2.draw(new

Line2D.Double(0,

px,

0,

py));

}

}

/*預(yù)覽指定的頁(yè)面*/

public

void

viewPage(int

pos)

{

int

newPage

=

currentPage

+

pos;

//指定頁(yè)面在實(shí)際的范圍內(nèi)

if

(0

<=

newPage

&&

newPage

<

preview.getPagesCount(printStr))

{

currentPage

=

newPage;

//將指定頁(yè)面賦值為當(dāng)前頁(yè)

repaint();

}

}

這樣,在按下"Next"按鈕時(shí),只需要調(diào)用canvas.viewPage(1);而在按下"Preview"按鈕時(shí),只需要調(diào)用canvas.viewPage(-1)即可實(shí)現(xiàn)預(yù)覽的前后翻頁(yè)。

3.3

打印圖形

3.3.1應(yīng)用場(chǎng)景

在實(shí)際應(yīng)用中,我們還需要打印圖形。譬如,我們有時(shí)需要將一個(gè)Java

Applet的完整界面或一個(gè)應(yīng)用程序窗體及其所包含的全部組件都打印出來,又應(yīng)該如何實(shí)現(xiàn)呢?

3.3.2解決方法

根本思路如下:在Java的Component類及其派生類中都提供了print和printAll方法,只要設(shè)置好屬性就可以直接調(diào)用這兩個(gè)方法,從而實(shí)現(xiàn)對(duì)組件及圖形的打印。

/*打印指定的窗體及其包含的組件*/

private

void

printFrameAction()

{

Toolkit

kit

=

Toolkit.getDefaultToolkit();

//獲取工具箱

Properties

props

=

new

Properties();

props.put("awt.print.printer",

"durango");

//設(shè)置打印屬性

props.put("awt.print.numCopies",

"2");

if

(kit

!=

null)

{

//獲取工具箱自帶的打印對(duì)象

PrintJob

printJob

=

kit.getPrintJob(this,

"Print

Frame",

props);

if

(printJob

!=

null)

{

Graphics

pg

=

printJob.getGraphics();

//獲取打印對(duì)象的圖形環(huán)境

if

(pg

!=

null)

{

try

{

this.printAll(pg);

//打印該窗體及其所有的組件

}

finally

{

pg.dispose();

//注銷圖形環(huán)境

}

}

printJob.end();

//完畢打印作業(yè)

}

}

}

3.4

打印文件

3.4.1應(yīng)用場(chǎng)景

在很多實(shí)際應(yīng)用情況下,我們可能都需要打印用戶指定的某一個(gè)文件。該文件可能是圖形文件,如GIF、JPEG等等;也可能是文本文件,如TXT、Java文件等等;還可能是復(fù)雜的PDF、DOC文件等等。那么對(duì)于這樣的打印需求,我們又應(yīng)該如何實(shí)現(xiàn)呢?

3.4.2解決方法

根本思路:在jdk1.4以前的版本,要實(shí)現(xiàn)這樣的打印功能將非常麻煩和復(fù)雜,甚至是難以想象的。但幸運(yùn)的是,jdk1.4的打印效勞API提供了一整套的打印文件流的類和方法。利用它們,我們可以非常方便快捷地實(shí)現(xiàn)各式各樣不同類型文件的打印功能。下面給出一個(gè)通用的處理方法。

/*打印指定的文件*/

private

void

print()

{

//構(gòu)造一個(gè)文件選擇器,默認(rèn)為當(dāng)前目錄

J

=

new

J(SystemProperties.USER_DIR);

int

state

=

(this);

//彈出文件選擇對(duì)話框

if

(state

==

)

//如果用戶選定了文件

{

=

();

//獲取選擇的文件

//構(gòu)建打印請(qǐng)求屬性集

PrintRequestAttributeSet

pras

=

new

HashPrintRequestAttributeSet();

//設(shè)置打印格式,因?yàn)槲创_定文件類型,這里選擇AUTOSENSE

DocFlavor

flavor

=

DocFlavor.INPUT_STREAM.AUTOSENSE;

//查找所有的可用打印效勞

PrintService

printService[]

=

PrintServiceLookup.lookupPrintServices(flavor,

pras);

//定位默認(rèn)的打印效勞

PrintService

defaultService

=

PrintServiceLookup.lookupDefaultPrin

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論