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