在这里实现了一个能模拟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!");
- }
- }
- }