/*
* 创建日期 2005-4-7
*
* TODO 要更改此生成的文件的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
package csvviewer;
import java.io.BufferedReader;
import java.io.*;
import java.io.IOException;
import javax.swing.table.TableColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
/**
* @author Administrator
*
*
*/
public class CSVViewer {
/**
* @author yantong
*
*
*/
private Shell shell;
private Display display;
private Text textBox;
private Table table;
private Label statusBar;
private MenuItem mItemOpen;
private final String[] EXTENSIONS = { "*.csv", "*" };
private String fileName;
public Shell open(Display display) {
this.display = display;
shell = new Shell(display);
shell.setText("CSVViewer");
shell.setLayout(new GridLayout(1, true));
Composite comp = new Composite(shell, SWT.NO_FOCUS);
comp.setLayout(new GridLayout(1, true));
GridData compGrid = new GridData();
compGrid.horizontalAlignment = GridData.FILL;
compGrid.verticalAlignment = GridData.FILL;
compGrid.grabExcessHorizontalSpace = true;
compGrid.grabExcessVerticalSpace = true;
comp.setLayoutData(compGrid);
textBox = new Text(comp, SWT.SINGLE | SWT.BORDER);
textBox.setText("");
GridData textGrid = new GridData();
textGrid.horizontalAlignment = GridData.FILL;
textGrid.grabExcessHorizontalSpace = true;
textBox.setLayoutData(textGrid);
createTable(comp);
statusBar = new Label(shell, SWT.LEFT);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
statusBar.setLayoutData(gridData);
statusBar.setText("指定CSV文件");
Menu menubar = new Menu(shell, SWT.BAR);
shell.setMenuBar(menubar);
MenuItem mItemFile = new MenuItem(menubar, SWT.CASCADE);
mItemFile.setText("文件(&F)");
Menu menuFile = new Menu(mItemFile);
mItemFile.setMenu(menuFile);
mItemOpen = new MenuItem(menuFile, SWT.PUSH);
mItemOpen.setText("打开(&O)");
mItemOpen.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
getOpenFileName();
if (fileName != null) {
new Thread(new CSVLoader()).start();
// loadBegin();
// loadFile();
// loadEnd();
}
}
});
//new MenuItem(menuFIle,SWT.SEPARATOR);
MenuItem mItemExit = new MenuItem(menuFile, SWT.PUSH);
mItemExit.setText("关闭(&X)");
mItemExit.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
close();
}
});
shell.open();
return shell;
}
/**
* @param parent
*/
private void createTable(Composite parent) {
table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER);
GridData tableGrid = new GridData();
tableGrid.horizontalAlignment = GridData.FILL;
tableGrid.verticalAlignment = GridData.FILL;
tableGrid.grabExcessHorizontalSpace = true;
tableGrid.grabExcessVerticalSpace = true;
table.setLayoutData(tableGrid);
table.setLinesVisible(true);
table.setHeaderVisible(true);
TableColumn col = new TableColumn(SWT.LEFT);
col.setWidth(100);
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
setTableSelectedIndex();
}
});
}
private void getOpenFileName() {
FileDialog openDialog = new FileDialog(shell, SWT.OPEN);
openDialog.setFilterExtensions(EXTENSIONS);
fileName = openDialog.open();
}
private void close() {
shell.close();
shell.dispose();
}
private void setTableSelectedIndex() {
int index = table.getSelectionIndex();
statusBar.setText("第" + (index + 1) + "行");
}
//以下为了用其它线程处理显示过程
/* 1.生成Runnable类,可以做成一个单独文件,为了方便只在CSVViewer中制作一个内部类 */
/* 2.修改菜单处理程序,将调用loadBegin,loadFile,loadEnd的地方修改,
* 替换为线程执行,new Thread(new CSVLoader()).start();
/* 3.将loadBegin,loadFile,loadEnd方法都放在线程CSVLoader中处理,
* 使其能在其它线程中执行, */
/* 4.线程化问题,org.eclipse.swt.SWTException:
* 问题在于操作SWT的widget处理在UI线程之外的某处被运行
* 可使用display的syncExec和asyncExec方法将处理移送到UI线程中*/
/* 5.向UI移送处理,追加asyncExec方法(CSVLoader追加utility方法checkAsyncExec())
* 修改loadBegin,loadFile方法,改为使用checkAsyncExec方法在UI流中运行*/
class CSVLoader implements Runnable {
private long beginTime;
public void run() {
loadBegin();
loadFile();
loadEnd();
}
private void loadBegin() {
checkAsyncExec(new Runnable(){
public void run(){
mItemOpen.setEnabled(false);
textBox.setText(fileName);
Composite comp = table.getParent();
table.dispose();
createTable(comp);
comp.layout();
statusBar.setText("读入中...");
}
});
beginTime = System.currentTimeMillis();
// mItemOpen.setEnabled(false);
// textBox.setText(fileName);
// Composite comp = table.getParent();
// table.dispose();
// createTable(comp);
// comp.layout();
// statusBar.setText("读入中...");
// beginTime = System.currentTimeMillis();
}
private void loadFile() {
BufferedReader reader = null;
try {
File file = new File(fileName);
if (!file.exists()) {
return;
}
reader = new BufferedReader(new FileReader(file));
String line = null;
while ((line = reader.readLine()) != null) {
final String[] datas = line.split(",");
//为了在run方法内参照loadFile方法的local变量datas,将其定义为final
boolean isOK = checkAsyncExec(new Runnable(){
public void run(){
if (table.isDisposed()){
return;
}
for (int i = table.getColumnCount(); i < datas.length; i++) {
TableColumn column = new TableColumn(SWT.LEFT);
column.setWidth(100);
}
TableItem item = new TableItem(table, SWT.NULL);
item.setText(datas);
}
});
if (!isOK){
return;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void loadEnd() {
checkAsyncExec(new Runnable(){
public void run(){
if (mItemOpen.isDisposed()||statusBar.isDisposed()){
return;
}
mItemOpen.setEnabled(true);
long end = System.currentTimeMillis();
statusBar.setText("读入完了:处理时间"+(end-beginTime)+"微秒");
}
});
// mItemOpen.setEnabled(true);
// long end = System.currentTimeMillis();
// statusBar.setText("读入结束:处理时间" + (end - beginTime) + "微秒");
}
private boolean checkAsyncExec(Runnable r) {
if (!display.isDisposed()) {
display.asyncExec(r);
return true;
} else {
return false;
}
}
}
public static void main(String[] args) {
Display display = new Display();
CSVViewer viewer = new CSVViewer();
Shell shell = viewer.open(display);
while (!shell.isDisposed()) {
//通过readAndDispatch()方法显示画面和时间处理
//在SWT中,把生成显示项目并在循环内执行方法的线程称为UI线程。
//如果该UI线程调用处理花费的时间过长的话,那应用程序看上去就像停止了一样。
//应该在单独的线程中执行由用户时间触发的长时间操作,以便事件循环线程快速返回,
//并从应用程序的队列中访存下一个事件。
//(必须用显式锁定和序列化来控制从其他线程访问小窗口和平台API)
if (!display.readAndDispatch())
display.sleep();
//如果队列中没有事件可用,则显示进入睡眠状态,以使其它应用程序有机会运行。
}
display.dispose();
}
}