《Eclipse SWT/JFACE 核心應用》 清華大學出版社 13 SWT的高級應用 13.1 打印支持 SWT通過Printer類可以實現(xiàn)打印的功能,。Printer類與Display對象都屬于設(shè)備的一種,,都繼承自Device類。 SWT中涉及打印的類都在org.eclipse.swt.printing包中,,包括打印對話框類(PrintDialog),、打印類(Printer)、打印數(shù)據(jù)類(PrinterData),。 1. 打印類(Printer)和打印數(shù)據(jù)類(PrinterData) PrinterData對象通常通過打印對話框獲得,。也可以通過Printer.getDefaultPrinterData()獲得默認的PrinterData對象。 創(chuàng)建打印類Printer有兩種方法: ◆ Printer():創(chuàng)建默認的打印類,。例如: Printer printer = new Printer(); ◆ Printer(PrinterData data):通過PrinterData對象創(chuàng)建打印類,。例如: PrinterData data = Printer.getDefaultPrinterData(); Printer printer = new Printer(data);
打印的流程:startJob()->[第一頁startPage()->endPage(),……第N頁startPage()->endPage()]->cancelJob()或endJob(),。 舉例如下: package www.; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.printing.Printer; import org.eclipse.swt.printing.PrinterData; public class SimplePrint { /** * @param args */ public static void main(String[] args) { PrinterData data = Printer.getDefaultPrinterData(); if (data == null) { System.out.println("failed"); return; } Printer printer = new Printer(data); // 開始打印任務(wù) if (printer.startJob("Simple Print")) { Color black = printer.getSystemColor(SWT.COLOR_BLACK); Color gray = printer.getSystemColor(SWT.COLOR_GRAY); Color red = printer.getSystemColor(SWT.COLOR_RED); // 計算左邊距上邊距的位置 Rectangle trim = printer.computeTrim(0, 0, 0, 0); Point dpi = printer.getDPI(); int leftMargin = dpi.x + trim.x; int topMargin = dpi.y / 2 + trim.y; // 創(chuàng)建圖形上下文對象 GC gc = new GC(printer); Font font = gc.getFont(); // 打印第一頁 if (printer.startPage()) { gc.setBackground(gray); gc.setForeground(black); String testString = "This is donkey 1."; // 使用GC對象畫字符串的方法顯示字符 gc.drawString(testString, leftMargin, topMargin+font.getFontData()[0].getHeight()); printer.endPage(); } // 打印第二頁 if (printer.startPage()) { gc.setBackground(gray); gc.setForeground(black); String testString = "This is donkey 2."; Point extent = gc.stringExtent(testString); // 使用GC對象畫字符串的方法顯示字符 gc.drawString(testString, leftMargin, topMargin+font.getFontData()[0].getHeight()); gc.setForeground(red); gc.drawRectangle(leftMargin, topMargin, extent.x, extent.y); printer.endPage(); } // 釋放GC對象 gc.dispose(); // 結(jié)束打印任務(wù) printer.endJob(); } printer.dispose(); } } 第一頁為灰色底黑字,第二頁為黑色底黑字帶紅色邊框,。 2. 打印程序示例 該程序的功能大致是:有一個文本框和菜單,,可以通過菜單項打開一個文件,并將內(nèi)容顯示在文本框中,。同時也可以設(shè)置顯示在文本框中文字的字體,、前景色,、背景色,設(shè)置好后,,可以選擇打印菜單項,,按照當前的格式打印出來。
PrintGUI.java: package www..ch13; import java.io.*; public class PrintGUI { private Shell sShell ; private Menu menu ; private Text content ; Font font; Color foregroundColor, backgroundColor; private void createMenu() { menu = new Menu ( sShell , SWT.BAR); sShell.setMenuBar( menu ); MenuItem item = new MenuItem(menu, SWT.CASCADE); item.setText("文件(&F)"); Menu fileMenu = new Menu(sShell, SWT.DROP_DOWN); item.setMenu(fileMenu); item = new MenuItem(fileMenu, SWT.PUSH); item.setText("打開(&O)"); item.setAccelerator(SWT.CTRL + 'O'); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { menuOpen(); } }); item = new MenuItem(fileMenu, SWT.PUSH); item.setText("選擇字體"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { menuFont(); } }); item = new MenuItem(fileMenu, SWT.PUSH); item.setText("選擇前景色"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { menuForegroundColor(); } }); item = new MenuItem(fileMenu, SWT.PUSH); item.setText("選擇背景色"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { menuBackgroundColor(); } }); item = new MenuItem(fileMenu, SWT.PUSH); item.setText("打印(@P)"); item.setAccelerator(SWT.CTRL + 'P'); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { menuPrint(); } }); new MenuItem(fileMenu, SWT.SEPARATOR); item = new MenuItem(fileMenu, SWT.PUSH); item.setText("退出(&E)"); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { font.dispose(); foregroundColor.dispose(); backgroundColor.dispose(); System.exit(0); } }); } protected void menuPrint() { PrintDialog dialog = new PrintDialog(sShell, SWT.NONE); PrinterData data = dialog.open(); if (data == null) return; if (data.printToFile) { data.fileName = "print.out"; } Printer printer = new Printer(data); TextPrinter textPrinter = new TextPrinter( "Print Job", content , printer); textPrinter.start(); } protected void menuBackgroundColor() { ColorDialog colorDialog = new ColorDialog(sShell); colorDialog.setRGB(content.getBackground().getRGB()); RGB rgb = colorDialog.open(); if (rgb != null) { if (backgroundColor != null) backgroundColor.dispose(); backgroundColor = new Color(sShell.getDisplay(), rgb); content.setBackground(backgroundColor); } } protected void menuForegroundColor() { ColorDialog colorDialog = new ColorDialog(sShell); colorDialog.setRGB(content.getForeground().getRGB()); RGB rgb = colorDialog.open(); if (rgb != null) { if (foregroundColor != null) foregroundColor.dispose(); foregroundColor = new Color(sShell.getDisplay(), rgb); content.setForeground(foregroundColor); } } protected void menuFont() { FontDialog fontDialog = new FontDialog(sShell); fontDialog.setFontList(content.getFont().getFontData()); FontData fontData = fontDialog.open(); if (fontData != null) { if (font != null) font.dispose(); font = new Font(sShell.getDisplay(), fontData); content.setFont(font); } } protected void menuOpen() { final String textString; FileDialog dialog = new FileDialog(sShell, SWT.OPEN); dialog.setFilterExtensions(new String[] {"*.java", "*.*"}); String name = dialog.open(); if ((name == null) || (name.length() == 0)) return;
try { File file = new File(name); FileInputStream stream= new FileInputStream(file.getPath()); try { Reader in = new BufferedReader(new InputStreamReader(stream)); char[] readBuffer= new char[2048]; StringBuffer buffer= new StringBuffer((int) file.length()); int n; while ((n = in.read(readBuffer)) > 0) { buffer.append(readBuffer, 0, n); } textString = buffer.toString(); stream.close(); } catch (IOException e) { MessageBox box = new MessageBox(sShell, SWT.ICON_ERROR); box.setMessage("讀文件出錯:\n" + name); box.open(); return; } } catch (FileNotFoundException e) { MessageBox box = new MessageBox(sShell, SWT.ICON_ERROR); box.setMessage("文件未找到:\n" + name); box.open(); return; } content.setText(textString); } private void createSShell() { sShell = new Shell(); sShell.setText("Shell"); sShell.setLayout(new FillLayout()); sShell.setSize(new Point(300, 200)); content = new Text(sShell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL); createMenu(); } public static void main(String[] args) { Display display = Display.getDefault(); PrintGUI thisClass = new PrintGUI(); thisClass.createSShell(); thisClass.sShell.open(); while (!thisClass.sShell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } }
TextPrinter.java: package www..ch13; import org.eclipse.swt.graphics.*; public class TextPrinter extends Thread { private Text content;//顯示字符的文本框?qū)ο?br>private Printer printer;//打印對象 private GC gc;//用于繪制的圖形上下文對象 private FontData[] printerFontData;//打印的字體數(shù)據(jù) private RGB printerForeground, printerBackground;//打印的前景色和背景色 private int lineHeight = 0;//打印的行高 private int tabWidth = 0;//Tab鍵的大小 private int leftMargin, rightMargin, topMargin, bottomMargin;//上下左右的頁邊距 private int x, y;//打印的行和列的值 private int index, end;//字符當前打印的索引值和總長度 private String textToPrint;//需要打印的字符 private String tabs;//Tab鍵 private StringBuffer wordBuffer;//打印字符的臨時變量 public TextPrinter(String name, Text text, Printer printer) { super(name); this.content = text; this.printer = printer; init(); } //初始化屬性的方法 public void init() { textToPrint = content.getText(); printerFontData = content.getFont().getFontData(); printerForeground = content.getForeground().getRGB(); printerBackground = content.getBackground().getRGB(); //默認一個Tab鍵表示4個空格 int tabSize = 4; StringBuffer tabBuffer = new StringBuffer(tabSize); for (int i = 0; i < tabSize; i++) tabBuffer.append(' '); tabs = tabBuffer.toString(); //計算上下左右邊距值 Rectangle clientArea = printer.getClientArea(); Rectangle trim = printer.computeTrim(0, 0, 0, 0); Point dpi = printer.getDPI(); leftMargin = dpi.x + trim.x; rightMargin = clientArea.width - dpi.x + trim.x + trim.width; topMargin = dpi.y + trim.y; bottomMargin = clientArea.height - dpi.y + trim.y + trim.height; } public void run() { //啟動打印,,如果不能正常啟動則返回 if (!printer.startJob("Text Print")) return; //開始打印 print(); } public void print() { //創(chuàng)建圖形上下文對象 gc = new GC(printer); //創(chuàng)建字體,,前景色,背景色對象 Font printerFont = new Font(printer, printerFontData); Color printerForegroundColor = new Color(printer, printerForeground); Color printerBackgroundColor = new Color(printer, printerBackground); //將字體,,前景色,,背景色設(shè)置給gc對象 gc.setFont(printerFont); gc.setForeground(printerForegroundColor); gc.setBackground(printerBackgroundColor); tabWidth = gc.stringExtent(tabs).x; lineHeight = gc.getFontMetrics().getHeight(); //打印字符 printText(); //結(jié)束打印工作 printer.endJob(); //釋放資源 printerFont.dispose(); printerForegroundColor.dispose(); printerBackgroundColor.dispose(); gc.dispose(); } void printText() { //開始打印一頁 printer.startPage(); wordBuffer = new StringBuffer(); x = leftMargin; y = topMargin; index = 0; end = textToPrint.length(); //循環(huán)每個字符串的每個字符 while (index < end) { char c = textToPrint.charAt(index); System.out.println(c); index++; if (c == 0) continue; //如果字符是\n換行符或\r回車符 if (c == '\n' || c == '\r'){ //如果字符\r\n同時出現(xiàn),則只打印一行 if (c == '\r' && index < end && textToPrint.charAt(index) == '\n') { index++; } printWordBuffer(); newline(); } else { //如果字符是不是Tab鍵,,則打印出字符 if (c != '\t') { wordBuffer.append(c); } if (Character.isWhitespace(c)) { printWordBuffer(); if (c == '\t') {//Tab鍵 x += tabWidth; } } } } if (y + lineHeight <= bottomMargin) { printer.endPage(); } } //打印字符,,要判斷是否已經(jīng)到了行的末尾,如果到了末尾需要換行 void printWordBuffer() { if (wordBuffer.length() > 0) { String word = wordBuffer.toString(); int wordWidth = gc.stringExtent(word).x; if (x + wordWidth > rightMargin) { newline(); } gc.drawString(word, x, y, false); x += wordWidth; wordBuffer = new StringBuffer(); } } //換行,,如果到了頁尾,,需要打印下一頁 void newline() { x = leftMargin; y += lineHeight; if (y + lineHeight > bottomMargin) { printer.endPage(); if (index + 1 < end) { y = topMargin; printer.startPage(); } } } }
打印程序執(zhí)行的過程:循環(huán)每個要打印的字符,如果字符是一個特殊的字符,,比如“\r”回車鍵,、“\n”換行鍵和“\t”Tab鍵值時要做特殊的處理,另外打印每個字符時還要考慮是否該換行和換頁等,。
預覽效果:
13.2 使用應用程序 SWT中提供了訪問其他應用程序的類Program,。通過該類可以打開系統(tǒng)中的其他應用程序。
Program類的靜態(tài)方法: ◆ getExtensions():獲得操作系統(tǒng)中所有支持的擴展名類型,。 String[] s = Program.getExtensions(); for (int i = 0; i < s.length; i++) { System.out.println(i +":" + s[i]); } ◆ getPrograms():獲得操作系統(tǒng)所安裝的所有的應用程序,。 Program[] programs = Program.getPrograms(); for (int i = 0; i < programs.length; i++) { System.out.println(i +":" + programs[i].getName()); } ◆ launch(String fileName):通過指定的應用程序的可執(zhí)行文件的地址,可打開一個應用程序,。 Program.launch("IExplore.exe"); Program.launch("C:\\Program Files\\Internet Explorer\\IExplore.exe"); ◆ findProgram(String extension):通過文件的擴展名來獲得打開該文件的應用程序,。 13.3 對AWT/Swing程序的支持 雖然AWT與SWT程序兩種桌面應用的運行機制不同,但為了使AWT的程序可以輕松的轉(zhuǎn)換到SWT程序中運行,,SWT提供了對AWT程序的支持,。對AWT程序支持的類在org.eclipse.swt.awt包中,該包中只有一個類AWT_SWT負責對SWT的控件和AWT控件的轉(zhuǎn)化,。該類有兩個方法,,負責進行轉(zhuǎn)換,如下所示: ◆ static java.awt.Frame new_Frame(Composite parent):該方法負責將SWT的面板對象轉(zhuǎn)化成AWT的Frame對象,,但使用時要注意,,傳入的parent對象的樣式要為SWT.EMBEDDED。 package www..ch13; import java.awt.Label; public class SWT_AWT_Sample { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setText("SWT and Swing/AWT Example"); shell.setLayout( new FillLayout()); //定義一個面板類,,樣式設(shè)置為SWT.EMBEDDED Composite composite = new Composite(shell, SWT.EMBEDDED); //將該面板對象轉(zhuǎn)化成AWT中的Frame對象 java.awt.Frame awtFrame = SWT_AWT.new_Frame(composite); awtFrame.setSize(200,150); awtFrame.setVisible( true ); //添加一個AWT標簽 java.awt.Label label = new Label(); label.setText("這是一個AWT標簽"); awtFrame.add( label ,java.awt.BorderLayout.NORTH); ////添加一個AWT文本框 TextField textField = new TextField(); textField.setText("這是一個AWT文本框"); awtFrame.add( textField ,java.awt.BorderLayout.CENTER); shell.pack(); shell.open(); while(!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } } 顯示效果:
◆ Shell new_Shell(Display display, java.awt.Canvas parent):該方法可以將一個AWT的Canvas對象轉(zhuǎn)化成SWT的Shell對象,。該方法的使用過程與剛才講述的方法相反,。 13.4 OLE和ActiveX控件的支持 OLE(Object Link Embeded)是指在程序之間鏈接和嵌入對象數(shù)據(jù)。通過OLE技術(shù)可以在一個應用程序中執(zhí)行其他的應用程序,。 而ActiveX控件是OLE的延伸,,一般用于網(wǎng)絡(luò)。 SWT中涉及OLE和ActiveX的類都在org.eclipse.swt.ole.win32包中,,使用最常見的是OleFrame類,、OleClientSite類和OleControlSite類。 1. OLE控件的面板類(OleFrame) 該類繼承自Composite類,,相當于一個放置OLE控件的面板,。 該類的主要功能有以下幾點: ◆ 對OLE控件進行布局的設(shè)置,相當于一個普通的面板類,。 ◆ 可以為控件添加菜單,。 ◇ 設(shè)置和獲取文件菜單:setFileMenus(MenuItem[] fileMenus)和getFileMenus()。 ◇ 設(shè)置和獲取容器菜單:setContainerMenus(MenuItem[] containerMenus)和getContainerMenus(),。 ◇ 設(shè)置和獲取窗口菜單:setWindowMenus(MenuItem[] windowMenus)和getWindowMenus(),。 ◆ 既然可以獲取OLE控件的菜單,就可以對菜單項進行控制,,例如設(shè)置可見和設(shè)置加速鍵等,。 創(chuàng)建一個OleFrame對象的方法: frame = new OleFrame(sShell, SWT.NONE); // 為控件設(shè)置菜單項 frame.setFileMenus(fileItem);
2. OLE控件類(OleClientSite和OleControlSite) OleClientSite對象和OleControlSite對象都是OLE控件,其中OleClientSite為OLE控件,,OleControlSite為ActiveX控件,,因為OleControlSite類繼承自O(shè)leClientSite類。
若想創(chuàng)建OLE對象,,有兩種常用的構(gòu)造方法: ◆ OleClientSite(Composite parent, int style, String progId):progId為標示應用系統(tǒng)的字符,,例如,Word的progId為“Word.Document”,,Excel的為“Excel.Sheet”,,IE的為“Shell.Explorer”。若要查看其他應用程序的progId,,可以查看系統(tǒng)注冊表,。 OleClientSite clientSite = new OleClientSite(frame, SWT.NONE, "Word.Document"); ◆ OleClientSite(Composite parent, int style, File file):file為保存的某一個文件。用這種方法創(chuàng)建的OLE控件,,系統(tǒng)會根據(jù)文件自動查找對應打開的應用程序,。 File file = new File("F:\\Temp.doc"); OleClientSite clientSite = new OleClientSite(frame, SWT.NONE, file);
創(chuàng)建了一個OLE控件,接下來需要打開控件,,才可以顯示控件,。使用doVerb(int verb)方法。其中verb有以下可以選擇的參數(shù): ◇ OLE.OLEIVERB_PRIMARY:打開編輯狀態(tài)的OLE控件,。 ◇ OLE.OLEIVERB_SHOW:顯示OLE控件,。 ◇ OLE.OLEIVERB_OPEN:在另外一個窗口中打開OLE控件。 ◇ OLE.OLEIVERB_HIDE:隱藏OLE控件,。 ◇ OLE.OLEIVERB_INPLACEACTIVATE:不帶有工具欄和菜單欄的方式,。 ◇ OLE.OLEIVERB_UIACTIVATE:激活OLE的菜單欄和工具欄。 ◇ OLE.OLEIVERB_DISCARDUNDOSTATE:關(guān)閉OLE控件,。 例如,,以下代碼可以打開編輯狀態(tài)的OLE控件: clientSite.doVerb(OLE.OLEIVERB_PRIMARY);
當OLE對打開的文件修改后,通過isDirty()方法可以判斷是否已經(jīng)修改過,。如果修改后,,可以使用save(File file, boolean includeOleInfo)方法進行保存。例如: if(clientSite.isDirty()) { clientSite.save(file, true); }
創(chuàng)建ActiveX控件對象要使用OleControlSite類,,該類只有一個構(gòu)造方法: OleControlSite(Composite parent, int style, String progId):只能根據(jù)progId來創(chuàng)建,。例如,創(chuàng)建一個Word的ActiveX控件對象的代碼如下: OleControlSite controlSite = new OleControlSite(frame, SWT.NONE, "Word.Document"); 3. OLE程序示例: 該程序的功能是:可以選擇打開Word文檔,,然后進行編輯后保存該文檔,。 package www..ch13; import java.io.File; public class OleSample { private Shell sShell; private MenuItem[] fileItem;//OLE的菜單項 private OleClientSite clientSite;//OLE控件對象 private OleFrame frame;//OLE的面板的對象 private File openFile;//打開的文件 public static void main(String[] args) { Display display = Display.getDefault(); OleSample thisClass = new OleSample(); thisClass.createSShell(); thisClass.sShell.open(); while (!thisClass.sShell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } thisClass.clientSite.dispose(); display.dispose(); } private void createSShell() { sShell = new Shell(); sShell.setText("OLE Sample"); sShell.setLayout(new FillLayout()); createMenu(); sShell.setSize(new Point(300, 200)); } //創(chuàng)建OLE控件對象 private void createOle() { frame = new OleFrame(sShell, SWT.NONE); frame.setFileMenus(fileItem); // 設(shè)置文件菜單 if (openFile != null) clientSite = new OleClientSite(frame, SWT.NONE, openFile); clientSite.doVerb(OLE.OLEIVERB_PRIMARY); } private void createMenu() { Menu main = new Menu(sShell, SWT.BAR); MenuItem file = new MenuItem(main, SWT.CASCADE); file.setText("文件(&F)"); Menu fileMenu = new Menu(file); fileItem = new MenuItem[2]; fileItem[0] = new MenuItem(fileMenu, SWT.PUSH); fileItem[0].setText("打開"); fileItem[1] = new MenuItem(fileMenu, SWT.PUSH); fileItem[1].setText("保存"); file.setMenu(fileMenu); sShell.setMenuBar(main); fileItem[0].addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { FileDialog dialog = new FileDialog(sShell, SWT.OPEN); dialog.setFilterExtensions(new String[] { "*.doc", "*.*" }); String file = dialog.open(); if (file != null) { openFile = new File(file); //打開OLE控件 createOle(); } } }); fileItem[1].addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { //如果打開文件被修改過 if (clientSite.isDirty()) { //創(chuàng)建一個臨時文件 File tempFile = new File(openFile.getAbsolutePath() + ".tmp"); openFile.renameTo(tempFile); //如果保存成功,則刪除臨時文件,,否則恢復到臨時文件保存的狀態(tài) if (clientSite.save(openFile, true)) tempFile.delete(); else tempFile.renameTo(openFile); } } }); } } 顯示效果:
打開一個Word文檔后:
“文件”菜單為在代碼中定義的菜單,,其他菜單為Word的菜單。 13.5 Pocket PC應用 在移動設(shè)備中使用的SWT程序與之前學習的SWT程序編寫代碼的方式?jīng)]有什么不同,。但是與之前SWT程序所不同的是,,SWT程序運行的環(huán)境不同,要在移動設(shè)備上運行SWT程序,,需要作以下配置: (1)確保移動設(shè)備上安裝了虛擬機(VM),,例如J2ME的運行環(huán)境,來確保能運行Java程序,。 (2)下載并安裝SWT所需的類庫swt.jar和與本地系統(tǒng)相關(guān)的.dll文件,。因為移動設(shè)備的內(nèi)存和存儲的資源有限,所以與桌面應用的SWT類庫相比,,移動設(shè)備上使用的SWT類庫大小上少很多,。 (3)最后運行編譯好的類文件。在移動設(shè)備上不可能安裝Eclipse,,所以要使用命令行來運行程序,。
13.6 Web應用SWT 通過第三方廠商的開發(fā)可以實現(xiàn)將SWT程序應用于Web開發(fā)。例如SmartSWT:http://www./smartswt/index.htm,。 安裝了SmartSWT服務(wù)器和客戶端,,就可以通過IE來訪問SWT程序,與我們平時瀏覽網(wǎng)頁沒什么區(qū)別了。
|