13.1 打印支持 SWT通过Printer类可以实现打印的功能。Printer类与Display对象都属于设备的一种,都继承自Device类。 SWT中涉及打印的类都在org.eclipse.swt.printing包中,包括打印对话框类(PrintDialog)、打印类(Printer)、打印数据类(PrinterData)。
1. 打印类(Printer)和打印数据类(PrinterData) PrinterData对象通常通过打印对话框获得。也可以通过Printer.getDefaultPrinterData()获得默认的PrinterData对象。 创建打印类Printer有两种方法:◆ Printer():创建默认的打印类。例如:Printer printer = new Printer();◆ Printer(PrinterData data):通过PrinterData对象创建打印类。例如:PrinterData data = Printer.getDefaultPrinterData();Printer printer = new Printer(data);打印的流程:startJob()->[第一页startPage()->endPage(),……第N页startPage()->endPage()]->cancelJob()或endJob()。
举例如下:package www.swt.com;
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); // 开始打印任务 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; // 创建图形上下文对象 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(); // 结束打印任务 printer.endJob(); } printer.dispose();}}第一页为灰色底黑字,第二页为黑色底黑字带红色边框。
2. 打印程序示例 该程序的功能大致是:有一个文本框和菜单,可以通过菜单项打开一个文件,并将内容显示在文本框中。同时也可以设置显示在文本框中文字的字体、前景色、背景色,设置好后,可以选择打印菜单项,按照当前的格式打印出来。PrintGUI.java:package www.swt.com.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.swt.com.ch13;
import org.eclipse.swt.graphics.*;
public class TextPrinter extends Thread {
private Text content;//显示字符的文本框对象private Printer printer;//打印对象private GC gc;//用于绘制的图形上下文对象private FontData[] printerFontData;//打印的字体数据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() { //创建图形上下文对象 gc = new GC(printer); //创建字体,前景色,背景色对象 Font printerFont = new Font(printer, printerFontData); Color printerForegroundColor = new Color(printer, printerForeground); Color printerBackgroundColor = new Color(printer, printerBackground); //将字体,前景色,背景色设置给gc对象 gc.setFont(printerFont); gc.setForeground(printerForegroundColor); gc.setBackground(printerBackgroundColor); tabWidth = gc.stringExtent(tabs).x; lineHeight = gc.getFontMetrics().getHeight(); //打印字符 printText(); //结束打印工作 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(); //循环每个字符串的每个字符 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同时出现,则只打印一行 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(); }}//打印字符,要判断是否已经到了行的末尾,如果到了末尾需要换行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(); } }}
}
打印程序执行的过程:循环每个要打印的字符,如果字符是一个特殊的字符,比如“/r”回车键、“/n”换行键和“/t”Tab键值时要做特殊的处理,另外打印每个字符时还要考虑是否该换行和换页等。预览效果:
13.2 使用应用程序 SWT中提供了访问其他应用程序的类Program。通过该类可以打开系统中的其他应用程序。Program类的静态方法:◆ getExtensions():获得操作系统中所有支持的扩展名类型。 String[] s = Program.getExtensions(); for (int i = 0; i < s.length; i++) { System.out.println(i +":" + s[i]); }◆ getPrograms():获得操作系统所安装的所有的应用程序。 Program[] programs = Program.getPrograms(); for (int i = 0; i < programs.length; i++) { System.out.println(i +":" + programs[i].getName()); }◆ launch(String fileName):通过指定的应用程序的可执行文件的地址,可打开一个应用程序。 Program.launch("IExplore.exe"); Program.launch("C://Program Files//Internet Explorer//IExplore.exe");◆ findProgram(String extension):通过文件的扩展名来获得打开该文件的应用程序。
13.3 对AWT/Swing程序的支持 虽然AWT与SWT程序两种桌面应用的运行机制不同,但为了使AWT的程序可以轻松的转换到SWT程序中运行,SWT提供了对AWT程序的支持。对AWT程序支持的类在org.eclipse.swt.awt包中,该包中只有一个类AWT_SWT负责对SWT的控件和AWT控件的转化。该类有两个方法,负责进行转换,如下所示:◆ static java.awt.Frame new_Frame(Composite parent):该方法负责将SWT的面板对象转化成AWT的Frame对象,但使用时要注意,传入的parent对象的样式要为SWT.EMBEDDED。package www.swt.com.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()); //定义一个面板类,样式设置为SWT.EMBEDDED Composite composite = new Composite(shell, SWT.EMBEDDED); //将该面板对象转化成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对象转化成SWT的Shell对象。该方法的使用过程与刚才讲述的方法相反。
13.4 OLE和ActiveX控件的支持 OLE(Object Link Embeded)是指在程序之间链接和嵌入对象数据。通过OLE技术可以在一个应用程序中执行其他的应用程序。 而ActiveX控件是OLE的延伸,一般用于网络。 SWT中涉及OLE和ActiveX的类都在org.eclipse.swt.ole.win32包中,使用最常见的是OleFrame类、OleClientSite类和OleControlSite类。
1. OLE控件的面板类(OleFrame) 该类继承自Composite类,相当于一个放置OLE控件的面板。
该类的主要功能有以下几点:◆ 对OLE控件进行布局的设置,相当于一个普通的面板类。◆ 可以为控件添加菜单。 ◇ 设置和获取文件菜单:setFileMenus(MenuItem[] fileMenus)和getFileMenus()。 ◇ 设置和获取容器菜单:setContainerMenus(MenuItem[] containerMenus)和getContainerMenus()。 ◇ 设置和获取窗口菜单:setWindowMenus(MenuItem[] windowMenus)和getWindowMenus()。◆ 既然可以获取OLE控件的菜单,就可以对菜单项进行控制,例如设置可见和设置加速键等。创建一个OleFrame对象的方法: frame = new OleFrame(sShell, SWT.NONE);// 为控件设置菜单项 frame.setFileMenus(fileItem);2. OLE控件类(OleClientSite和OleControlSite) OleClientSite对象和OleControlSite对象都是OLE控件,其中OleClientSite为OLE控件,OleControlSite为ActiveX控件,因为OleControlSite类继承自OleClientSite类。若想创建OLE对象,有两种常用的构造方法:◆ OleClientSite(Composite parent, int style, String progId):progId为标示应用系统的字符,例如,Word的progId为“Word.Document”,Excel的为“Excel.Sheet”,IE的为“Shell.Explorer”。若要查看其他应用程序的progId,可以查看系统注册表。OleClientSite clientSite = new OleClientSite(frame, SWT.NONE, "Word.Document");◆ OleClientSite(Composite parent, int style, File file):file为保存的某一个文件。用这种方法创建的OLE控件,系统会根据文件自动查找对应打开的应用程序。File file = new File("F://Temp.doc");OleClientSite clientSite = new OleClientSite(frame, SWT.NONE, file);
创建了一个OLE控件,接下来需要打开控件,才可以显示控件。使用doVerb(int verb)方法。其中verb有以下可以选择的参数:◇ OLE.OLEIVERB_PRIMARY:打开编辑状态的OLE控件。◇ OLE.OLEIVERB_SHOW:显示OLE控件。◇ OLE.OLEIVERB_OPEN:在另外一个窗口中打开OLE控件。◇ OLE.OLEIVERB_HIDE:隐藏OLE控件。◇ OLE.OLEIVERB_INPLACEACTIVATE:不带有工具栏和菜单栏的方式。◇ OLE.OLEIVERB_UIACTIVATE:激活OLE的菜单栏和工具栏。◇ OLE.OLEIVERB_DISCARDUNDOSTATE:关闭OLE控件。例如,以下代码可以打开编辑状态的OLE控件:clientSite.doVerb(OLE.OLEIVERB_PRIMARY);
当OLE对打开的文件修改后,通过isDirty()方法可以判断是否已经修改过。如果修改后,可以使用save(File file, boolean includeOleInfo)方法进行保存。例如:if(clientSite.isDirty()) {clientSite.save(file, true);}创建ActiveX控件对象要使用OleControlSite类,该类只有一个构造方法:OleControlSite(Composite parent, int style, String progId):只能根据progId来创建。例如,创建一个Word的ActiveX控件对象的代码如下:OleControlSite controlSite = new OleControlSite(frame, SWT.NONE, "Word.Document");
3. OLE程序示例: 该程序的功能是:可以选择打开Word文档,然后进行编辑后保存该文档。
package www.swt.com.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));}//创建OLE控件对象private void createOle() { frame = new OleFrame(sShell, SWT.NONE); frame.setFileMenus(fileItem); // 设置文件菜单 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()) { //创建一个临时文件 File tempFile = new File(openFile.getAbsolutePath() + ".tmp"); openFile.renameTo(tempFile); //如果保存成功,则删除临时文件,否则恢复到临时文件保存的状态 if (clientSite.save(openFile, true)) tempFile.delete(); else tempFile.renameTo(openFile); } } });}}显示效果:
打开一个Word文档后:“文件”菜单为在代码中定义的菜单,其他菜单为Word的菜单。
13.5 Pocket PC应用 在移动设备中使用的SWT程序与之前学习的SWT程序编写代码的方式没有什么不同。但是与之前SWT程序所不同的是,SWT程序运行的环境不同,要在移动设备上运行SWT程序,需要作以下配置:(1)确保移动设备上安装了虚拟机(VM),例如J2ME的运行环境,来确保能运行Java程序。(2)下载并安装SWT所需的类库swt.jar和与本地系统相关的.dll文件。因为移动设备的内存和存储的资源有限,所以与桌面应用的SWT类库相比,移动设备上使用的SWT类库大小上少很多。(3)最后运行编译好的类文件。在移动设备上不可能安装Eclipse,所以要使用命令行来运行程序。13.6 Web应用SWT 通过第三方厂商的开发可以实现将SWT程序应用于Web开发。例如SmartSWT:http://www.smartswt.net/smartswt/index.htm。 安装了SmartSWT服务器和客户端,就可以通过IE来访问SWT程序,与我们平时浏览网页没什么区别了。