使用swt模拟eclipse控制台显示打印信息

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

猜你喜欢

转载自jarip.iteye.com/blog/1759074