从零开始—我的开源项目7:GUI+判断哪些jar包是必须的依赖

想给程序增加一个可视化界面。从学习java开始,就一直没有怎么接触过gui编程,gui也确实被妖魔化、边缘化的比较严重。

简单查看了一些资料,发现对图像化的软件十分感兴趣,有些无法自拔的趋势。

一篇关于GUI文章的大神如是写到:“会不能代表什么,但是不会就能代表什么了”。

但迫于时间,只好忍痛,草草收场,导致很多设想没有实现,很多细节也没有完善。

先谈一下对v0.0.3代码的改造。

为了实现进度条功能,在excelUtil中增加了一个excels属性,用来判断excel中需要操作的数据条数。

excelUtil.java 代码如下

package com.crick.excel2word.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.crick.excel2word.core.enumeration.OfficeFileType;

public class ExcelUtil extends OfficeFileUtil {

	public ExcelUtil(String fullPath) {
		super(fullPath);
	}
	
	private int excels = 0;
	public int getExcels() {
		return excels;
	}
	
	public List<File> scanDirExcel(String dirPath) {
		return super.scanDir(dirPath,OfficeFileType.EXCEL_03_TYPE,OfficeFileType.EXCEL_07UP_TYPE);
	}
	
	public List<Map<String,Object>> extract() {
		List<Map<String,Object>> results = new ArrayList<Map<String,Object>>();
		Workbook book;
		try {
			book = new HSSFWorkbook(new BufferedInputStream(new FileInputStream(getFile())));
			Sheet sheet = book.getSheetAt(0);
			if (sheet.getLastRowNum() == 0) {
				return null;
			}
			this.excels = sheet.getLastRowNum();
			List<String> keys = getKeyList(sheet.getRow(0));
			for (int i=sheet.getFirstRowNum()+1; i <= sheet.getLastRowNum(); i++) {
				Map<String,Object> param = extractRow(sheet.getRow(i),keys);
				results.add(param);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return results;
	}
	
	private Map<String,Object> extractRow(Row row,List<String> keys){
		Map<String,Object> params = new HashMap<String,Object>();
		for (int i=0; i<row.getLastCellNum(); i++) {
			if (keys.get(i) == null || keys.get(i) == "") {
				continue;
			}
			row.getCell(i).setCellType(Cell.CELL_TYPE_STRING);
			params.put("#{"+keys.get(i)+"}",row.getCell(i));
		}
		return params; 
	}
	
	/**
	 * 第一行作为key,即mark标签名
	 * 
	 * @param row
	 * @return
	 */
	private List<String> getKeyList(Row row) {
		List<String> keys = new ArrayList<String>();
		for (int i=0; i<=row.getLastCellNum();i++) {
			if (row.getCell(i) != null) {
				row.getCell(i).setCellType(Cell.CELL_TYPE_STRING);
			} 
			keys.add(row.getCell(i)==null?"":row.getCell(i).toString().toLowerCase());
		}
		//如果未指定name标签,则默认第一列为生成的word文件名
		if (!keys.contains("name")) {
			keys.set(0,"name");
		}
		return keys;
	}
}
因为WordUtil是对单个word文件的操作,无法判断word文件的数量,所以将words属性放在Excel2Words类中,并提供getProgress方法获取进度百分比。

修改后的Excel2Words.java代码如下:

package com.crick.excel2word;

import java.io.File;
import java.util.List;
import java.util.Map;

import com.crick.excel2word.util.ExcelUtil;
import com.crick.excel2word.util.WordUtil;

public class Excel2Words {

	private static WordUtil wordUtil;
	private static ExcelUtil excelUtil;
	private static int words = 0;
	
	private static void init(String wordPath,String excelPath) {
		wordUtil = new WordUtil(wordPath);
		excelUtil = new ExcelUtil(excelPath);
	}

	public static void autoExport(String wordPath,String excelPath,String exportDir) {
		init(wordPath,excelPath);
		if (!exportDir.endsWith(File.separator)) {
			exportDir = exportDir.concat(File.separator);
		}
		List<Map<String,Object>> rowList = excelUtil.extract();
		for (Map<String,Object> rowParam : rowList) {
			wordUtil.export(rowParam,exportDir,rowParam.get("#{name}").toString());
			words++;
		}
	}
	
	public static int getProgress() {
		return words*100/excelUtil.getExcels();
	}
}

图形化界面是通过eclipse,基于SWF和JFace制作而成。附Eclipse相关插件地址:http://download.eclipse.org/windowbuilder/WB/release/R201309271200/4.3/

能力有限,只是实现了基本功能,而代码层面,应该也没有达到比较好的实现,所以只是贴出代码,不做讲解。


MainWin.java依赖于v0.0.3打包生成的excel2word-0.0.3-SNAPSHOT-jar-with-dependencies.jar,代码如下:

package gui;

import org.eclipse.jface.action.CoolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.crick.excel2word.Excel2Words;

public class MainWin extends ApplicationWindow {

	private String wordPath;
	private String excelPath;
	private String exportDir;
	private ProgressBar progressBar;
	private Text wordPathText;
	private Text excelPathText;
	private Text exportDirText;
	
	private void clear() {
		wordPath = "";
		excelPath = "";
		exportDir = "";
		wordPathText.setText("");
		excelPathText.setText("");
		exportDirText.setText("");
		progressBar.setSelection(0);
		progressBar.dispose();
	}
	
	private void showProgress(Composite parent) {
		progressBar = new ProgressBar(parent,SWT.NONE);
		progressBar.setBounds(20,200,550,25);
		progressBar.setMinimum(0);
		progressBar.setMaximum(100);
		new Thread() {
			public void run() {
					getShell().getDisplay().asyncExec(new Runnable() {
						public void run() {
							while (progressBar.getSelection() < progressBar.getMaximum()) { 
								try {
									progressBar.setSelection(Excel2Words.getProgress());
									Thread.sleep(100);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
							MessageDialog.openInformation(getShell(),"完成","word文件已经生成成功,请在" + exportDirText.getText() + "目录下查看。");
							clear();
						}
					});
				}
		}.start();
	}
	
	/**
	 * Create the application window,*/
	public MainWin() {
		super(null);
		addCoolBar(SWT.FLAT);
		addMenuBar();
		addStatusLine();
	}

	/**
	 * Create contents of the application window.
	 * @param parent
	 */
	@Override
	protected Control createContents(Composite parent) {
		final Composite container = new Composite(parent,SWT.NONE);
		
		wordPathText = new Text(container,SWT.H_SCROLL | SWT.CANCEL | SWT.CENTER);
		wordPathText.setEditable(false);
		wordPathText.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
		wordPathText.setFont(new Font(Display.getCurrent(),"微软雅黑",11,SWT.NORMAL));
		wordPathText.setText("word文件");
		wordPathText.setBounds(20,30,505,25);
		
		Label label1 = new Label(container,SWT.SEPARATOR | SWT.VERTICAL);
		label1.setBounds(527,2,25);
		
		final FileDialog wordDialog = new FileDialog(getShell());
		Button selectWordBtn = new Button(container,SWT.NONE);
		selectWordBtn.setBounds(530,40,25);
		selectWordBtn.setText("选择");
		selectWordBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				wordPath = wordDialog.open();
				wordPathText.setText(wordPath);
			}
		});
		
		excelPathText = new Text(container,SWT.H_SCROLL | SWT.CANCEL | SWT.CENTER);
		excelPathText.setEditable(false);
		excelPathText.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
		excelPathText.setFont(new Font(Display.getCurrent(),SWT.NORMAL));
		excelPathText.setText("excel文件");
		excelPathText.setBounds(20,70,25);
		
		Label label2 = new Label(container,SWT.SEPARATOR | SWT.VERTICAL);
		label2.setBounds(527,25);
		
		final FileDialog excelDialog = new FileDialog(getShell());
		Button selectExcelBtn = new Button(container,SWT.NONE);
		selectExcelBtn.setBounds(530,25);
		selectExcelBtn.setText("选择");
		
		selectExcelBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				excelPath = excelDialog.open();
				excelPathText.setText(excelPath);
			}
		});
		
		exportDirText = new Text(container,SWT.H_SCROLL | SWT.CANCEL | SWT.CENTER);
		exportDirText.setEditable(false);
		exportDirText.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
		exportDirText.setFont(new Font(Display.getCurrent(),SWT.NORMAL));
		exportDirText.setText("保存路径");
		exportDirText.setBounds(20,110,25);
		
		Label label3 = new Label(container,SWT.SEPARATOR | SWT.VERTICAL);
		label3.setBounds(527,25);
		
		final DirectoryDialog exportDialog = new DirectoryDialog(getShell());
		Button selectExportBtn = new Button(container,SWT.NONE);
		selectExportBtn.setBounds(530,25);
		selectExportBtn.setText("选择");
		
		selectExportBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				exportDir = exportDialog.open();
				exportDirText.setText(excelPath);
			}
		});
		
		Button button = new Button(container,SWT.CHECK);
		button.setBounds(370,140,15);
		button.setText("打包压缩");
		
		Button startBtn = new Button(container,SWT.NONE);
		startBtn.setBounds(150,160,300,25);
		startBtn.setText("开 始");
		startBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				showProgress(container);
				Excel2Words.autoExport(wordPath,excelPath,exportDir);
			}
		});
		
		return container;
	}

	/**
	 * Create the menu manager.
	 * @return the menu manager
	 */
	@Override
	protected MenuManager createMenuManager() {
		MenuManager menuManager = new MenuManager("menu");
		return menuManager;
	}

	/**
	 * Create the coolbar manager.
	 * @return the coolbar manager
	 */
	@Override
	protected CoolBarManager createCoolBarManager(int style) {
		CoolBarManager coolBarManager = new CoolBarManager(style);
		return coolBarManager;
	}

	/**
	 * Create the status line manager.
	 * @return the status line manager
	 */
	@Override
	protected StatusLineManager createStatusLineManager() {
		StatusLineManager statusLineManager = new StatusLineManager();
		return statusLineManager;
	}

	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String args[]) {
		try {
			MainWin window = new MainWin();
			//使 open() 阻塞,直到窗口关闭为止
			window.setBlockOnOpen(true);
			window.open();
			Display.getCurrent().dispose();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Configure the shell.
	 * @param newShell
	 */
	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Excel parse to Words");
	}

	/**
	 * Return the initial size of the window.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(600,360);
	}
}

这时有一个问题:由于是通过eclipse直接创建的SWT/JFace项目,所以依赖了众多的eclipse插件的jar包文件。


怎么能判断出项目依赖了哪些jar包,筛选出必需的依赖包呢?

第一步:利用eclipse将项目打包成jar文件。

详情见从零开始—我的开源项目5:代码完善(中)


第二步:通过-verbose:class判断使用了哪些.class文件

java -jar -verbose:class excel2word-0.0.4.jar >>dependents.txt

因为v0.0.4只有一个java文件,否则,则需要把各功能都使用一遍,以此找到所有的依赖文件。

dependents.txt中生成的文件内容如下:



第三步:遍历依赖包文件目录,根据文件名是否存在于dependents.txt中,以此判断文件是否被依赖。

第四步:将依赖的jar文件复制到新目录内

将这两步放在一起的原因是因为我们要通过程序实现,我直接遍历的eclipse的plugins目录,具体代码如下:

package util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

public class CopyDependentJar {
	public static void main(String[] args) throws IOException {
		String classTxt = readClassTxt();
		File file = new File("D:\\eclipse_kepler\\plugins");
		for (File f : file.listFiles()) {
			if (classTxt.contains(f.getName())) {
				copy(f,"D:\\cut\\dependents");
			}
		}
	}
	
	private static String readClassTxt() throws IOException {
		File file = new File("D:\\cut\\dependents.txt");
		BufferedReader re = new BufferedReader(new FileReader(file));
		StringBuffer sb = new StringBuffer();
		String line = re.readLine();
		while (line != null) {
			sb.append(line);
			line = re.readLine();
		}
		re.close();
		return sb.toString();
	}
	
	private static void copy(File srcFile,String outDirPath) throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
		File outDir = new File(outDirPath);
		if (!outDir.exists()) {
			outDir.mkdir();
		}
		File outFile = new File(outDirPath + File.separator + srcFile.getName());
		if (!outFile.exists()) {
			outFile.createNewFile();
		}
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outFile));
		byte[] chs = new byte[1024];
		int len = bis.read(chs,chs.length);
		while(len != -1){
			bos.write(chs,len);
			len = bis.read(chs,chs.length);
		}
		bos.close();
		bis.close();
	}
}

将dependents目录下的文件和excel2word-0.0.3-SNAPSHOT-jar-with-dependencies.jar一起放入项目的lib目录下,添加依赖,ok,搞定。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结