最近想做一個功能,就是把我們編譯後的位元組碼及其資原始檔打包成一個可執行的jar包,在裝有jre的機器上雙擊就能執行。
首先是我們需要選擇哪些位元組碼和檔案需要打包到檔案中,這個我們用JFileChooser來做,讓使用者選擇,我做了一個窗體來讓使用者選擇。
效果如下:
我們讓瀏覽檔案系統,並選擇需要打包的資料夾,然後計算出可以作為啟動類的檔案,通過下方的下拉讓使用者選擇。
生成檔案路徑在確認按鈕點選後彈出檔案儲存框讓使用者選擇就好(也可以彈出輸入框)。
程式碼如下:
Main
1 package org.coderecord.commons.ejarmaker; 2 3 import java.awt.EventQueue; 4 5 import javax.swing.UIManager; 6 import javax.swing.UnsupportedLookAndFeelException; 7 8 public class Main { 9 10 public static void main(String[] args) { 11 try { 12 UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); 13 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { 14 e.printStackTrace(); 15 } 16 EventQueue.invokeLater(new Runnable() { 17 18 @Override 19 public void run() { 20 new FrmMain().setVisible(true); 21 } 22 }); 23 } 24 25 }
FrmMain(只是介面程式碼,業務程式碼最後貼出)
1 package org.coderecord.commons.ejarmaker; 2 3 import java.awt.Toolkit; 4 import java.awt.event.ActionEvent; 5 import java.awt.event.ActionListener; 6 import java.io.File; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 import javax.swing.JButton; 11 import javax.swing.JComboBox; 12 import javax.swing.JFileChooser; 13 import javax.swing.JFrame; 14 import javax.swing.JLabel; 15 import javax.swing.JScrollPane; 16 import javax.swing.JTextArea; 17 import javax.swing.filechooser.FileFilter; 18 19 public class FrmMain extends JFrame implements ActionListener { 20 21 private static final long serialVersionUID = 2016913328739206536L; 22 // 選擇的檔案(使用者在檔案選擇器中選擇的) 23 private List<File> userSelectedFiles = new ArrayList<>(); 24 // 我們經過分析得到的最終會被打包的檔案 25 private List<File> finalFiles = new ArrayList<>(); 26 27 public FrmMain() { 28 setSize(480, 320); 29 setResizable(false); 30 setLocationRelativeTo(null); 31 setTitle("通用可執行Jar包生成工具"); 32 setDefaultCloseOperation(EXIT_ON_CLOSE); 33 setLayout(null); 34 // 在執行時獲取資原始檔的方式,一定是使用Class.getResource方式 35 // 在jar包中這種方式也行得通 36 // ‘/’代表根路徑 37 setIconImage(Toolkit.getDefaultToolkit().getImage(FrmMain.class.getResource("/resources/icon.png"))); 38 initComponents(); 39 } 40 41 // 初始化元件 42 private void initComponents() { 43 // 提示 44 lblTip = new JLabel("選擇需要打包的檔案並設定啟動類"); 45 lblTip.setLocation(20, 10); 46 lblTip.setSize(350, 20); 47 add(lblTip); 48 49 // 瀏覽按鈕 50 btnBrowser = new JButton("瀏 覽"); 51 btnBrowser.setLocation(380, 10); 52 btnBrowser.setSize(80, 24); 53 btnBrowser.addActionListener(this); 54 add(btnBrowser); 55 56 // 展示已選擇檔案 57 JScrollPane jspFiles = new JScrollPane(); 58 txtFiles = new JTextArea(); 59 txtFiles.setEditable(false); 60 jspFiles.setSize(440, 160); 61 jspFiles.setLocation(20, 40); 62 txtFiles.setSize(440, 201600); 63 txtFiles.setLocation(20, 40); 64 txtFiles.setFocusable(false); 65 jspFiles.setViewportView(txtFiles); 66 add(jspFiles); 67 68 // 選擇啟動類 69 cobMainClass = new JComboBox<>(); 70 cobMainClass.setSize(440, 30); 71 cobMainClass.setLocation(20, 210); 72 add(cobMainClass); 73 74 // 清除已選 75 btnCls = new JButton("重 選"); 76 btnCls.setLocation(20, 250); 77 btnCls.setSize(80, 24); 78 btnCls.addActionListener(this); 79 add(btnCls); 80 81 // 確認按鈕 82 btnConfirm = new JButton("確認"); 83 btnConfirm.setSize(80, 24); 84 btnConfirm.setLocation(380, 250); 85 btnConfirm.addActionListener(this); 86 add(btnConfirm); 87 88 // 檔案選擇器 89 jfcSelect = new JFileChooser(); 90 // 可以選擇檔案和資料夾 91 jfcSelect.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 92 // 可以多選 93 jfcSelect.setMultiSelectionEnabled(true); 94 95 // 檔案儲存 96 jfcSave = new JFileChooser(); 97 // 設定只接受以“.jar”結尾的檔案 98 jfcSave.setAcceptAllFileFilterUsed(false); 99 jfcSave.setFileFilter(new FileFilter() { 100 101 @Override 102 public String getDescription() { 103 return "可執行Jar"; 104 } 105 106 @Override 107 public boolean accept(File f) { 108 return f.getName().endsWith(".jar"); 109 } 110 }); 111 } 112 113 @Override 114 public void actionPerformed(ActionEvent e) { 115 116 } 117 118 private JLabel lblTip; 119 private JButton btnBrowser; 120 private JFileChooser jfcSelect; 121 private JTextArea txtFiles; 122 private JComboBox<String> cobMainClass; 123 private JButton btnCls; 124 private JButton btnConfirm; 125 private JFileChooser jfcSave; 126 }
然後開始業務部分,首先是選擇檔案,我們允許使用者選擇多個檔案和資料夾(甚至可以通過多次選擇來選擇不同碟符、路徑下的檔案和資料夾),在選擇後可能有重複的地方或兩次選擇後有包含的專案,我們要去除。
我們為“瀏覽”按鈕事件新增處理,讓使用者選擇檔案並處理選中檔案:
1 @Override 2 public void actionPerformed(ActionEvent e) { 3 if(e.getSource() == btnBrowser) { 4 // 瀏覽 5 int result = jfcSelect.showOpenDialog(this); 6 7 // 選擇了檔案 8 if(result == JFileChooser.APPROVE_OPTION) { 9 for(File file : jfcSelect.getSelectedFiles()) 10 userSelectedFiles.add(file); 11 12 // 整理選擇的檔案,去除重複項 13 removeDuplicateItems(userSelectedFiles); 14 15 // 重新計算選中檔案 16 finalFiles.clear(); 17 for(File file : userSelectedFiles) 18 addFileToList(file, finalFiles); 19 20 // 計算檔案展示打包路徑及展示路徑 21 // 計算可啟動類路徑 22 // 展示到文字框中 23 cobMainClass.removeAllItems(); 24 txtFiles.setText(""); 25 File file,direc; 26 String filePath,direcPath; 27 Iterator<File> itd,itf; 28 for(itd = userSelectedFiles.iterator(); itd.hasNext();) { 29 direc = itd.next(); 30 direcPath = direc.getAbsolutePath(); 31 for(itf = finalFiles.iterator(); itf.hasNext();) { 32 file = itf.next(); 33 filePath = file.getAbsolutePath(); 34 if(filePath.equalsIgnoreCase(direcPath)) { 35 txtFiles.append(file.getName() + "\n"); 36 filePaths.put(file.getName(), file); 37 //fileNames.put(file.getName(), file.getName().endsWith(".class")?file.getName().substring(0, file.getName().lastIndexOf('.')):file.getName()); 38 if(file.getName().endsWith(".class")) 39 cobMainClass.addItem(file.getName().endsWith(".class")?file.getName().substring(0, file.getName().lastIndexOf('.')):file.getName()); 40 itf.remove(); 41 } else if(filePath.startsWith(direcPath)) { 42 String nameTmp = filePath.substring(direcPath.lastIndexOf(File.separator) + 1).replace(File.separatorChar, '/'); 43 filePaths.put(nameTmp, file); 44 txtFiles.append(nameTmp + "\n"); 45 //fileNames.put(nameTmp, nameTmp.endsWith(".class")?nameTmp.substring(0, nameTmp.lastIndexOf('.')).replace('/', '.'):nameTmp); 46 if(nameTmp.endsWith(".class") && nameTmp.indexOf('$') == -1) 47 cobMainClass.addItem(nameTmp.substring(0, nameTmp.lastIndexOf('.')).replace('/', '.')); 48 itf.remove(); 49 } 50 } 51 } 52 } 53 } 54 } 55 56 // 新增檔案(非資料夾)到集合 57 private void addFileToList(File file, List<File> fileArr) { 58 if(file.isDirectory()) 59 for(File child : file.listFiles()) 60 addFileToList(child, fileArr); 61 else 62 fileArr.add(file); 63 } 64 65 // 去除重複項 66 private void removeDuplicateItems(List<File> fileArr) { 67 // 去重複項 68 Set<String> directories = new HashSet<>(); 69 Set<String> files = new HashSet<>(); 70 for(File file : fileArr) 71 if(file.isDirectory()) 72 directories.add(file.getAbsolutePath()); 73 else 74 files.add(file.getAbsolutePath()); 75 //去包含項(先去資料夾再去檔案應該更好) 76 String fpath,dpath; 77 for(Iterator<String> itf = files.iterator(); itf.hasNext();) { 78 fpath = itf.next(); 79 for(Iterator<String> itd = directories.iterator(); itd.hasNext();) { 80 dpath = itd.next(); 81 if(fpath.startsWith(dpath)) 82 itf.remove(); 83 } 84 } 85 String dpath1,dpath2; 86 Set<String> directories1 = new HashSet<>(directories); 87 for(Iterator<String> itd1 = directories.iterator(); itd1.hasNext();) { 88 dpath1 = itd1.next(); 89 for(Iterator<String> itd2 = directories1.iterator(); itd2.hasNext();) { 90 dpath2 = itd2.next(); 91 if(dpath1.equals(dpath2)) 92 continue; 93 else if(dpath2.startsWith(dpath1)) 94 itd2.remove(); 95 else if(dpath1.startsWith(dpath2)) 96 itd1.remove(); 97 } 98 } 99 directories.addAll(directories1); 100 101 fileArr.clear(); 102 for(String file : files) 103 fileArr.add(new File(file)); 104 for(String directory : directories) 105 fileArr.add(new File(directory)); 106 }
“重選”按鈕點選後清除已選項,邏輯就先不詳細介紹了。
然後是“確定”按鈕,我們彈出檔案儲存框讓使用者選擇儲存位置,然後生成可執行的jar包:
1 @Override 2 public void actionPerformed(ActionEvent e) { 3 if(e.getSource() == btnBrowser) { 4 } else if(e.getSource() == btnCls) { 5 if(userSelectedFiles.size() == 0) return; 6 else if(JOptionPane.showConfirmDialog(this, "確定重選嗎?將清除所有已選項!") == JOptionPane.OK_OPTION) { 7 userSelectedFiles.clear(); 8 finalFiles.clear(); 9 filePaths.clear(); 10 cobMainClass.removeAllItems(); 11 } 12 } else if(e.getSource() == btnConfirm) { 13 if(filePaths.size() == 0) { 14 JOptionPane.showMessageDialog(this, "未選擇檔案", "錯誤", JOptionPane.ERROR_MESSAGE); 15 return; 16 } else if(cobMainClass.getSelectedItem() == null) { 17 JOptionPane.showMessageDialog(this, "未選擇啟動類", "錯誤", JOptionPane.ERROR_MESSAGE); 18 return; 19 } 20 // 打包 21 int result = jfcSave.showSaveDialog(this); 22 if(result == JFileChooser.APPROVE_OPTION) { 23 try { 24 // 清單檔案 25 Manifest man = new Manifest(); 26 // 版本和啟動類路徑必要 27 man.getMainAttributes().putValue(Name.MANIFEST_VERSION.toString(), "1.0"); 28 man.getMainAttributes().putValue(Name.MAIN_CLASS.toString(), cobMainClass.getSelectedItem().toString()); 29 // Class-Path一定不要,除非能保證將引用類(即import的類)都聯合打包了 30 JarOutputStream jos = new JarOutputStream(new FileOutputStream(jfcSave.getSelectedFile()), man); 31 jos.setLevel(Deflater.BEST_COMPRESSION); 32 BufferedInputStream bis = null; 33 byte[] cache = new byte[1024]; 34 StringBuffer config = new StringBuffer(); 35 for(String name : filePaths.keySet()) { 36 bis = new BufferedInputStream(new FileInputStream(filePaths.get(name)), 1024); 37 config.append(name).append('=').append(bis.available()).append('\n'); 38 jos.putNextEntry(new JarEntry(name)); 39 int count; 40 while((count = bis.read(cache, 0, 1024)) != -1) 41 jos.write(cache, 0, count); 42 jos.closeEntry(); 43 bis.close(); 44 } 45 jos.flush(); 46 jos.close(); 47 JOptionPane.showMessageDialog(this, "匯出成功!", "成功", JOptionPane.INFORMATION_MESSAGE); 48 System.exit(0); 49 } catch(Exception ex) { 50 JOptionPane.showMessageDialog(this, ex.getMessage(), "異常", JOptionPane.ERROR_MESSAGE); 51 System.exit(1); 52 } 53 } 54 } 55 56 }
當然,這裡還有一個小問題:選擇檔案(自己寫的檔名就算不加字尾也能儲存成功-_-)。
先展示一下結果:
在檔案系統中選擇:
匯出到桌面:
執行一下:
我最後再將完整的原始碼貼出一份:
1 package org.coderecord.commons.ejarmaker; 2 3 import java.awt.Toolkit; 4 import java.awt.event.ActionEvent; 5 import java.awt.event.ActionListener; 6 import java.io.BufferedInputStream; 7 import java.io.File; 8 import java.io.FileInputStream; 9 import java.io.FileOutputStream; 10 import java.util.ArrayList; 11 import java.util.HashSet; 12 import java.util.Hashtable; 13 import java.util.Iterator; 14 import java.util.List; 15 import java.util.Map; 16 import java.util.Set; 17 import java.util.jar.JarEntry; 18 import java.util.jar.JarOutputStream; 19 import java.util.jar.Manifest; 20 import java.util.jar.Attributes.Name; 21 import java.util.zip.Deflater; 22 23 import javax.swing.JButton; 24 import javax.swing.JComboBox; 25 import javax.swing.JFileChooser; 26 import javax.swing.JFrame; 27 import javax.swing.JLabel; 28 import javax.swing.JOptionPane; 29 import javax.swing.JScrollPane; 30 import javax.swing.JTextArea; 31 import javax.swing.filechooser.FileFilter; 32 33 public class FrmMain extends JFrame implements ActionListener { 34 35 private static final long serialVersionUID = 2016913328739206536L; 36 // 選擇的檔案(使用者在檔案選擇器中選擇的) 37 private List<File> userSelectedFiles = new ArrayList<>(); 38 // 我們經過分析得到的最終會被打包的檔案 39 private List<File> finalFiles = new ArrayList<>(); 40 // 檔案打包路徑及物理檔案 41 private Map<String, File> filePaths = new Hashtable<>(); 42 43 public FrmMain() { 44 setSize(480, 320); 45 setResizable(false); 46 setLocationRelativeTo(null); 47 setTitle("通用可執行Jar包生成工具"); 48 setDefaultCloseOperation(EXIT_ON_CLOSE); 49 setLayout(null); 50 // 在執行時獲取資原始檔的方式,一定是使用Class.getResource方式 51 // 在jar包中這種方式也行得通 52 // ‘/’代表根路徑 53 setIconImage(Toolkit.getDefaultToolkit().getImage(FrmMain.class.getResource("/resources/icon.png"))); 54 initComponents(); 55 } 56 57 // 初始化元件 58 private void initComponents() { 59 // 提示 60 lblTip = new JLabel("選擇需要打包的檔案並設定啟動類"); 61 lblTip.setLocation(20, 10); 62 lblTip.setSize(350, 20); 63 add(lblTip); 64 65 // 瀏覽按鈕 66 btnBrowser = new JButton("瀏 覽"); 67 btnBrowser.setLocation(380, 10); 68 btnBrowser.setSize(80, 24); 69 btnBrowser.addActionListener(this); 70 add(btnBrowser); 71 72 // 展示已選擇檔案 73 JScrollPane jspFiles = new JScrollPane(); 74 txtFiles = new JTextArea(); 75 txtFiles.setEditable(false); 76 jspFiles.setSize(440, 160); 77 jspFiles.setLocation(20, 40); 78 txtFiles.setSize(440, 201600); 79 txtFiles.setLocation(20, 40); 80 txtFiles.setFocusable(false); 81 jspFiles.setViewportView(txtFiles); 82 add(jspFiles); 83 84 // 選擇啟動類 85 cobMainClass = new JComboBox<>(); 86 cobMainClass.setSize(440, 30); 87 cobMainClass.setLocation(20, 210); 88 add(cobMainClass); 89 90 // 清除已選 91 btnCls = new JButton("重 選"); 92 btnCls.setLocation(20, 250); 93 btnCls.setSize(80, 24); 94 btnCls.addActionListener(this); 95 add(btnCls); 96 97 // 確認按鈕 98 btnConfirm = new JButton("確認"); 99 btnConfirm.setSize(80, 24); 100 btnConfirm.setLocation(380, 250); 101 btnConfirm.addActionListener(this); 102 add(btnConfirm); 103 104 // 檔案選擇器 105 jfcSelect = new JFileChooser(); 106 // 可以選擇檔案和資料夾 107 jfcSelect.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 108 // 可以多選 109 jfcSelect.setMultiSelectionEnabled(true); 110 111 // 檔案儲存 112 jfcSave = new JFileChooser(); 113 // 設定只接受以“.jar”結尾的檔案 114 jfcSave.setAcceptAllFileFilterUsed(false); 115 jfcSave.setFileFilter(new FileFilter() { 116 117 @Override 118 public String getDescription() { 119 return "可執行Jar"; 120 } 121 122 @Override 123 public boolean accept(File f) { 124 return f.getName().endsWith(".jar"); 125 } 126 }); 127 } 128 129 @Override 130 public void actionPerformed(ActionEvent e) { 131 if(e.getSource() == btnBrowser) { 132 // 瀏覽 133 int result = jfcSelect.showOpenDialog(this); 134 135 // 選擇了檔案 136 if(result == JFileChooser.APPROVE_OPTION) { 137 for(File file : jfcSelect.getSelectedFiles()) 138 userSelectedFiles.add(file); 139 140 // 整理選擇的檔案,去除重複項 141 removeDuplicateItems(userSelectedFiles); 142 143 // 重新計算選中檔案 144 finalFiles.clear(); 145 for(File file : userSelectedFiles) 146 addFileToList(file, finalFiles); 147 148 // 計算檔案展示打包路徑及展示路徑 149 // 計算可啟動類路徑 150 // 展示到文字框中 151 cobMainClass.removeAllItems(); 152 txtFiles.setText(""); 153 File file,direc; 154 String filePath,direcPath; 155 Iterator<File> itd,itf; 156 for(itd = userSelectedFiles.iterator(); itd.hasNext();) { 157 direc = itd.next(); 158 direcPath = direc.getAbsolutePath(); 159 for(itf = finalFiles.iterator(); itf.hasNext();) { 160 file = itf.next(); 161 filePath = file.getAbsolutePath(); 162 if(filePath.equalsIgnoreCase(direcPath)) { 163 txtFiles.append(file.getName() + "\n"); 164 filePaths.put(file.getName(), file); 165 if(file.getName().endsWith(".class")) 166 cobMainClass.addItem(file.getName().endsWith(".class")?file.getName().substring(0, file.getName().lastIndexOf('.')):file.getName()); 167 itf.remove(); 168 } else if(filePath.startsWith(direcPath)) { 169 String nameTmp = filePath.substring(direcPath.lastIndexOf(File.separator) + 1).replace(File.separatorChar, '/'); 170 filePaths.put(nameTmp, file); 171 txtFiles.append(nameTmp + "\n"); 172 if(nameTmp.endsWith(".class") && nameTmp.indexOf('$') == -1) 173 cobMainClass.addItem(nameTmp.substring(0, nameTmp.lastIndexOf('.')).replace('/', '.')); 174 itf.remove(); 175 } 176 } 177 } 178 } 179 } else if(e.getSource() == btnCls) { 180 if(userSelectedFiles.size() == 0) return; 181 else if(JOptionPane.showConfirmDialog(this, "確定重選嗎?將清除所有已選項!") == JOptionPane.OK_OPTION) { 182 userSelectedFiles.clear(); 183 finalFiles.clear(); 184 filePaths.clear(); 185 cobMainClass.removeAllItems(); 186 } 187 } else if(e.getSource() == btnConfirm) { 188 if(filePaths.size() == 0) { 189 JOptionPane.showMessageDialog(this, "未選擇檔案", "錯誤", JOptionPane.ERROR_MESSAGE); 190 return; 191 } else if(cobMainClass.getSelectedItem() == null) { 192 JOptionPane.showMessageDialog(this, "未選擇啟動類", "錯誤", JOptionPane.ERROR_MESSAGE); 193 return; 194 } 195 // 打包 196 int result = jfcSave.showSaveDialog(this); 197 if(result == JFileChooser.APPROVE_OPTION) { 198 try { 199 // 清單檔案 200 Manifest man = new Manifest(); 201 // 版本和啟動類路徑必要 202 man.getMainAttributes().putValue(Name.MANIFEST_VERSION.toString(), "1.0"); 203 man.getMainAttributes().putValue(Name.MAIN_CLASS.toString(), cobMainClass.getSelectedItem().toString()); 204 // Class-Path一定不要,除非能保證將引用類(即import的類)都聯合打包了 205 JarOutputStream jos = new JarOutputStream(new FileOutputStream(jfcSave.getSelectedFile()), man); 206 jos.setLevel(Deflater.BEST_COMPRESSION); 207 BufferedInputStream bis = null; 208 byte[] cache = new byte[1024]; 209 StringBuffer config = new StringBuffer(); 210 for(String name : filePaths.keySet()) { 211 bis = new BufferedInputStream(new FileInputStream(filePaths.get(name)), 1024); 212 config.append(name).append('=').append(bis.available()).append('\n'); 213 jos.putNextEntry(new JarEntry(name)); 214 int count; 215 while((count = bis.read(cache, 0, 1024)) != -1) 216 jos.write(cache, 0, count); 217 jos.closeEntry(); 218 bis.close(); 219 } 220 jos.flush(); 221 jos.close(); 222 JOptionPane.showMessageDialog(this, "匯出成功!", "成功", JOptionPane.INFORMATION_MESSAGE); 223 System.exit(0); 224 } catch(Exception ex) { 225 JOptionPane.showMessageDialog(this, ex.getMessage(), "異常", JOptionPane.ERROR_MESSAGE); 226 System.exit(1); 227 } 228 } 229 } 230 231 } 232 233 // 新增檔案(非資料夾)到集合 234 private void addFileToList(File file, List<File> fileArr) { 235 if(file.isDirectory()) 236 for(File child : file.listFiles()) 237 addFileToList(child, fileArr); 238 else 239 fileArr.add(file); 240 } 241 242 // 去除重複項 243 private void removeDuplicateItems(List<File> fileArr) { 244 // 去重複項 245 Set<String> directories = new HashSet<>(); 246 Set<String> files = new HashSet<>(); 247 for(File file : fileArr) 248 if(file.isDirectory()) 249 directories.add(file.getAbsolutePath()); 250 else 251 files.add(file.getAbsolutePath()); 252 //去包含項(先去資料夾再去檔案應該更好) 253 String fpath,dpath; 254 for(Iterator<String> itf = files.iterator(); itf.hasNext();) { 255 fpath = itf.next(); 256 for(Iterator<String> itd = directories.iterator(); itd.hasNext();) { 257 dpath = itd.next(); 258 if(fpath.startsWith(dpath)) 259 itf.remove(); 260 } 261 } 262 String dpath1,dpath2; 263 Set<String> directories1 = new HashSet<>(directories); 264 for(Iterator<String> itd1 = directories.iterator(); itd1.hasNext();) { 265 dpath1 = itd1.next(); 266 for(Iterator<String> itd2 = directories1.iterator(); itd2.hasNext();) { 267 dpath2 = itd2.next(); 268 if(dpath1.equals(dpath2)) 269 continue; 270 else if(dpath2.startsWith(dpath1)) 271 itd2.remove(); 272 else if(dpath1.startsWith(dpath2)) 273 itd1.remove(); 274 } 275 } 276 directories.addAll(directories1); 277 278 fileArr.clear(); 279 for(String file : files) 280 fileArr.add(new File(file)); 281 for(String directory : directories) 282 fileArr.add(new File(directory)); 283 } 284 285 private JLabel lblTip; 286 private JButton btnBrowser; 287 private JFileChooser jfcSelect; 288 private JTextArea txtFiles; 289 private JComboBox<String> cobMainClass; 290 private JButton btnCls; 291 private JButton btnConfirm; 292 private JFileChooser jfcSave; 293 }
這裡有我匯出的檔案(這個是eclipse匯出的,它在manifest中加入了classPath沒有錯誤,我有時候加入後有問題)。
(最後編輯時間2014-03-02 16:12:50)