在这里实现了一个能模拟eclipse控制台显示打印信息的程序. 主要的技术点有下:
1, 输出流重定向:
将形如System.out.println();的输出内容重定向的原理:
(1) System类的静态属性 out 的类型是 PrintStream; System.out.println即是调用PrintStream实例的println方法;
(2) PrintStream 为其他输出流添加了功能,使它们能够方便地打印(列如打印到java控制台)各种数据值表示形式;
(3) 我们可以自己书写 PrintStream 的子类, 将 子类PrintStream实例 作为参数传入System.setOut(PrintStream out) 方法中;
(4) 这样,通过System.out调用打印方法输出到java控制台的内容将由自己定义的子类PrintStream进行处理;
(5) 本例中是把输出流重定向到SWT的Text部件里面;如果仅是想把输出流重定向到文件,则可以这样:
创建文件输出流: PrintStream out = new PrintStream("./txtFileName.txt");
设置使用新的输出流: System.setOut(out);
2, 在非UI线程(主线程) 访问UI的方式
在非UI线程访问UI, 可以使用Display.getDefault().syncExec操作UI控件
下面是程序运行中的界面:
下面是程序代码 (为了节省篇幅, 去掉了import语句, 在eclipse中可用快捷键 ctrl + shift + o 导入org.eclipse.swt和javaIO相关的包):
public class MenuTest { public static void main(String[] args) { Display display = new Display(); final Shell shell = new Shell(display); shell.setText("Console"); shell.setBounds(100, 100, 500, 400); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 1; shell.setLayout(gridLayout); //定义一个菜单,当点击File的Select Me Now选项时触发子线程中的循环打印 Menu menuBar = new Menu(shell, SWT.BAR); shell.setMenuBar(menuBar); MenuItem fileMenuItems = new MenuItem(menuBar, SWT.CASCADE); fileMenuItems.setText("&File"); Menu subMenu = new Menu(shell, SWT.DROP_DOWN); fileMenuItems.setMenu(subMenu); MenuItem selectItem = new MenuItem(subMenu, SWT.NULL); selectItem.setText("&Select Me Now"); selectItem.setAccelerator(SWT.CTRL + 'S'); selectItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { // 默认情况下监听事件时在主线程里执行 // 在子线程执行任务避免阻塞主线程 PrintThread printThread = new PrintThread("the First Item"); printThread.start(); } }); MenuItem sep = new MenuItem(subMenu, SWT.SEPARATOR); MenuItem exitItem = new MenuItem(subMenu, SWT.NULL); exitItem.setText("&Exit"); exitItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { shell.dispose(); } }); Text text = new Text(shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL)); //输出重定向设置 MyPrintStream mps = new MyPrintStream(System.out, text); System.setOut(mps); System.setErr(mps); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); System.exit(0); // 杀掉子线程,终止jvm } } //定义一个PrintStream子类,将打印语句输出流重定向到Text组件中显示 class MyPrintStream extends PrintStream { private Text text; public MyPrintStream(OutputStream out, Text text) { super(out); this.text = text; } // 重写父类write方法,这个方法是所有打印方法里面都要调用的方法 public void write(byte[] buf, int off, int len) { final String message = new String(buf, off, len); // SWT非界面线程访问组件的方式 Display.getDefault().syncExec(new Thread() { public void run() { // 把信息添加到组件中 if (text != null && !text.isDisposed()) { text.append(message); } } }); } } //在非UI线程中不断执行System.out.println()方法 class PrintThread extends Thread { private String name; public PrintThread(String name) { this.name = name; } public void run() { while (true) { System.out.println(name + "was selected!"); } } }