一、開發背景介紹:
1. 要開發什麼工具?
最近和公司裏的幾位同事湊錢買了個的士發票打印機(報銷用,你懂的^_^),內容可自己寫,比如金額,時間,路程等等。發票內容的輸出位置和文字樣式要跟真實發票的一樣,否則容易穿幫(嘻嘻...)。但位置、樣式要手工調,非常麻煩。所以如果有個工具能夠幫助我們調好位置和文字樣式的話,那就方便省事多了!!
2. 爲什麼強調要快速開發?
其實已經有個同事開發出這樣的工具了,所以一開始我也沒想過再造一個出來。但是當我好奇的問他用什麼語言開發的時候,他來了句“你可以自己開發一個嘛!我用C#啊!”!我如果沒理解錯,這是向我宣戰了。而我接受了這個挑戰。那天是週五快下班的時候,我決定下週一給他看看我的版本!
3.我爲什麼選擇SWT,而不選擇Swing?
Swing有太深的Java UI的烙印--UI控件的風格過於簡陋。既然要PK,起碼外觀上不能輸。而SWT的好處是它會調用底層操作系統提供的UI控件,因此UI風格比較友好,用戶覺得親切熟悉。還有一個好處是可在Eclipse上進行SWT可視化開發,這能極大提高開發速度!就它了!
終於說到正題了。
二、準備工作
1.Eclipse我用的是3.5 Galileo。
2.可視化工具:WindowBuilder ,可通過Eclipse在線安裝,這裏不多說了,可google下。
3.jar包轉exe工具:Jsmooth。
三、 實際開發
1. 先看看成果
2. 開發要點
2.1讀取Excel文件將內容顯示到表格中
核心代碼如下:
2.1.1 “導入”按鈕的觸發動作
- Button button_1 = new Button(shell, SWT.NONE);
- button_1.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent selectionevent) {
- String filePath = text.getText();
- showProgressDialog(filePath);
- }
- });
2.1.2 顯示進度條
- private void showProgressDialog(final String filePath) {
- try {
- final Display display = Display.getCurrent();
- ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(display.getActiveShell());
- final List<String[]> contents = new ArrayList<String[]>();
- IRunnableWithProgress progRunnable = new IRunnableWithProgress() {
- public void run(IProgressMonitor iprogressmonitor)
- throws InvocationTargetException, InterruptedException {
- int totalRow = 0;
- try {
- InputStream in = ExcelUtils.readExcelFile(filePath);
- // IProgressMonitor 爲監視器,可監控任務進度,此處設定任務總量爲100個單位
- iprogressmonitor.beginTask("努力爲你讀取文件,請稍候...", 100);
- Sheet sheet = ExcelUtils.retreiveSheet(in, 0);
- totalRow = sheet.getRows();
- int totalCol = sheet.getColumns();
- int rowStart = 0;
- int rowEnd = 0;
- int temp = totalRow / 10;
- int segLength = temp > 0 ? temp : 1;
- // 把任務人爲的分成10端
- for(int seg = 1; seg <= 10 && !iprogressmonitor.isCanceled(); seg++) {
- rowStart = rowEnd;
- rowEnd += segLength;
- for(int row = rowStart; row < rowEnd; row++) {
- List<String> rowContent = new ArrayList<String>();
- for(int c = 0; c < totalCol; c++) {
- Cell cell = sheet.getCell(c, row);
- rowContent.add(cell.getContents());
- }
- contents.add(rowContent.toArray(new String[0]));
- }
- //每完成一段監視器增加10個單位
- iprogressmonitor.worked(10);
- iprogressmonitor.subTask("已完成"+seg*10+"%");
- if(rowEnd >= totalRow) {
- break;
- }
- }
- // 完成剩餘的記錄(如果有的話)
- for(int k = rowEnd; k < totalRow; k++) {
- List<String> rowContent = new ArrayList<String>();
- for(int c = 0; c < totalCol; c++) {
- Cell cell = sheet.getCell(c, k);
- rowContent.add(cell.getContents());
- }
- contents.add(rowContent.toArray(new String[0]));
- }
- // 在非UI線程中更新UI,必須利用asyncExec 或者 syncExec
- display.asyncExec(new Runnable() {
- public void run() {
- // 向表格控件添加數據
- addTableItems(table,contents);
- }
- });
- iprogressmonitor.done();
- // 如果此時爲用戶取消的操作
- if (iprogressmonitor.isCanceled()) {
- throw new InterruptedException("用戶已取消操作");
- }
- }catch(Exception ex) {
- ex.printStackTrace();
- showMessgeBox(shell,ex.getMessage());
- }
- // showMessgeBox(shell,"已成功爲你讀取" + totalRow + "條記錄.");
- }
- };
- progressDialog.run(true, false, progRunnable);
- }catch(Exception ex) {
- ex.printStackTrace();
- }
- }
- private void addTableItems(Table table,List<String[]> contents) {
- for(String[] rowContents : contents) {
- TableItem tableItem = new TableItem(table, SWT.NONE);
- tableItem.setText(rowContents);
- }
- }
2.2 選中某一行數據後將數據格式化顯示
2.2.1效果如下:
2.2.2 核心代碼如下
- table.addListener(SWT.MouseUp, new Listener() {
- public void handleEvent(Event event) {
- int sTextWidth = initStyledText(Integer.parseInt(combo.getItem(combo
- .getSelectionIndex())),Integer.parseInt(spinner_3.getText()), Integer.parseInt(spinner_1
- .getText()));
- int charsNum = new Double(Math.ceil(sTextWidth/8.0)).intValue();
- int colCount = table.getColumnCount();
- TableItem[] selectedItems= table.getSelection();
- StringBuffer sb = new StringBuffer();
- int topLine = Integer.parseInt(spinner.getText());
- for(int line = 0; line < topLine; line++) {
- sb.append(LINE_SEPARATOR);
- }
- for(int i = 0; i < selectedItems.length; i++) {
- TableItem item = selectedItems[i];
- for(int j=0;j<colCount;j++) {
- String realText = item.getText(j);
- if(realText.length() < charsNum) {
- int spaces = charsNum - realText.getBytes().length;
- for(int k = 0;k < spaces;k++) {
- sb.append(" ");
- }
- }
- sb.append(item.getText(j)).append(LINE_SEPARATOR);
- }
- }
- styledText.setText(sb.toString());
- }
- });
- }
- /**
- * 文本樣式,如字體大小,行距,對齊等用StyledText來控制。
- * @param fontSize 字體大小
- * @param rightMove 右移位數
- * @param lineSpacing 行距
- * @return
- * @version: v1.0.0
- * @author: <a href="mailto:[email protected]">flysqrlboy</a>
- * @date: 2013-1-27
- */
- private int initStyledText(int fontSize,int rightMove,int lineSpacing) {
- styleTextFont = SWTResourceManager.getFont("宋體", fontSize, SWT.NORMAL);
- styledText.setFont(styleTextFont);
- styledText.setAlignment(SWT.LEFT);
- styledText.setJustify(true);
- styledText.setLineSpacing(lineSpacing);
- return styledTextSrcWidth + rightMove * 8;
- }
四、jar包轉成Exe執行文件
打成Exe可執行文件的目的是雙擊即可運行,當然運行目前這個版本的exe文件要求用戶的電腦中要有Java 運行時環境(JRE)。如果要在沒有JRE的電腦中運行,則在轉exe時把jre包一起打進exe文件中即可。
1.打jar包
這裏要注意的是,我們的目標是雙擊exe即可運行,無需依賴外部的資源,所以打jar包時要把所有依賴的jar都打進一個jar裏。
如下圖操作:
2. 用Jsmooth轉成EXE
這裏只說Application的配置,如下圖:
由於invoice.jar已經是可運行的jar(雙擊運行),所以上圖中的Classpath無需任何設置,即不必依賴外部資源。
至此,工具開發完成。週末兩天去除生活上一些雜七雜八的瑣事,開發時間應該在18小時內。
工具本身很輕巧沒什麼難度,不過把一個想法鼓搗出來的過程還是挺爽的!