0.寫在前面
2020-5-18 更新
這個東西已經是兩年前的了,現在問我具體細節我也不是很清楚了,而且現在review兩年前的代碼感覺寫的好爛。。。請大家有問題下面留言,不要加我的企鵝了,正在准備考研,比較忙。
一點建議:1.當時會的比較少,對象實例化對於單純的數據查詢來說效率極低而且很蠢,我現在更建議使用數據庫,或者簡單點用xml or json都可以,建議想寫的好一點的同學把里面的數據讀寫邏輯改一改,用數據庫不香嗎
2.這個是分客戶端服務端的,服務端相當於用底層手擼了一個相當簡單的tomcat,所有的界面都是要從Client進去的。先開server再開Client,在注冊時以邀請碼判斷是否為管理員。以管理員身份進入client之后再去添加信息。
3.如果注冊時報access is denied 在Flie的路徑下加一層文件夾,如下
小一個月沒更新博客了,主要是臨近期末,各科的大作業都下來了,今天把自己奮斗了一個禮拜的校園導航系統貼在上面,也算滿足下自己的小成就感('ᴗ' )و
實驗要求如下:
以我校為例,設計一個校園導航系統,主要為來訪的客人提供信息查詢。系統有兩類登陸賬號,一類是游客,使用該系統方便校內路線查詢;一類是管理員,可以使用該系統查詢校內路線,可對校園景點路線可編輯。
說簡單點,就是給定一個地圖數據,然后地圖上有好幾個點,每個點間有距離,這個程序提供了查詢兩點間最短路徑的功能。當然,你可以為他增加很多細節,比如查看景點信息啊,后台的管理啊等等,這些都是加分項。
老師推薦使用C,其實題目也是這么要求的。但是使用C有幾個比較麻煩的問題:
第一,要是只實現基本的功能用C的話肯定是沒什么問題,但是要是想添枝加葉的話,C的代碼就沒法看了,寫起來麻煩讀起來也難受。
第二,地圖是有地圖數據的,要是用C的話一般人都會直接printf N多行的地圖吧,這也是一個比較麻煩的事兒。
思來想去,我決定還是用Java來做這個系統,最短路徑用迪傑斯特拉算法。
其實我還是第一次用Java做一個功能比較多的程序,既然是第一次我就想做好點,做的與眾不同點。於是,我為這個程序增加了注冊登錄、邀請碼注冊管理員系統。
1.客戶端與服務端
題目中既然區分了一般用戶與管理員的權限,不如在這上面發揮一下。

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 import java.io.*; 6 import java.net.Socket; 7 8 public class Client 9 { 10 private JFrame jFrame; 11 private JLabel accountLabel, passwdLabel, inviteLabel; 12 private JTextField accountText, passwdText, inviteText; 13 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 14 private JPanel accountJPanel, passwdJPanel, buttonjPanel, invitejPanel; 15 private JButton loginButton, registButton; 16 static JDialog jDialog=new JDialog(); 17 18 private Font font = new Font("微軟雅黑", 1, 18); 19 20 private BufferedWriter bufferedWriter; 21 private BufferedReader bufferedReader; 22 23 private String account, passwd; 24 private String tips; 25 private boolean isAdmin = false; 26 27 public Client() 28 { 29 init(); 30 } 31 32 public void init() 33 { 34 jFrame = new JFrame("用戶登錄"); 35 jFrame.setLayout(new FlowLayout()); 36 jFrame.setBounds((toolkit.getScreenSize().width - 270) / 2, (toolkit.getScreenSize().height - 200) / 2, 270, 200); 37 38 componentInit(accountJPanel = new JPanel(), accountLabel = new JLabel(), accountText = new JTextField(), " 帳號"); 39 componentInit(passwdJPanel = new JPanel(), passwdLabel = new JLabel(), passwdText = new JTextField(), " 密碼"); 40 componentInit(invitejPanel = new JPanel(), inviteLabel = new JLabel(), inviteText = new JTextField(), "邀請碼"); 41 42 loginButtonInit(); 43 registButtonInit(); 44 45 jFrame.setVisible(true); 46 jFrame.setResizable(false); 47 48 } 49 50 public void componentInit(JPanel jPanel, JLabel jLabel, JTextField jTextField, String str) 51 { 52 jPanel.setLayout(new FlowLayout()); 53 54 jLabel.setText(str); 55 jLabel.setFont(font); 56 57 jTextField.setText(""); 58 jTextField.setColumns(14); 59 60 jPanel.add(jLabel); 61 jPanel.add(jTextField); 62 63 jFrame.add(jPanel); 64 } 65 66 public void loginButtonInit() 67 { 68 loginButton = new JButton("登錄"); 69 70 loginButton.addMouseListener(new MouseAdapter() 71 { 72 @Override 73 public void mouseClicked(MouseEvent e) 74 { 75 try 76 { 77 Socket socket = new Socket("localhost", 10001); 78 //每點擊一次必須新建一個新的Socket,否則無法一直獲取服務端的數據,具體原因不明,日后考證 79 sendInfo(0, socket); 80 if (tips.contains("成功")) 81 { 82 Home home = new Home(isAdmin); 83 } 84 } catch (IOException e1) 85 { 86 e1.printStackTrace(); 87 } 88 89 } 90 }); 91 jFrame.add(loginButton); 92 } 93 94 public void registButtonInit() 95 { 96 registButton = new JButton("注冊"); 97 registButton.addMouseListener(new MouseAdapter() 98 { 99 @Override 100 public void mouseClicked(MouseEvent e) 101 { 102 try 103 { 104 Socket socket = new Socket("localhost", 10001); 105 sendInfo(1, socket); 106 } catch (IOException e1) 107 { 108 e1.printStackTrace(); 109 } 110 111 } 112 }); 113 jFrame.add(registButton); 114 } 115 116 public void sendInfo(int code, Socket socket)//封裝了注冊登錄的共性方法 117 { 118 119 account = accountText.getText(); 120 passwd = passwdText.getText(); 121 String string; 122 if (code == 0) 123 { 124 string = "登錄"; 125 } 126 else 127 string = "注冊"; 128 try 129 { 130 bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 131 //這里同樣要使用每次的新的Socket獲取寫入流 132 133 bufferedWriter.write(code + "\r\n"); 134 bufferedWriter.flush();//輸出標示,告訴服務端是登錄還是注冊,登錄為0,注冊為1 135 136 bufferedWriter.write(account + "\r\n");//必須要有結束標示,否則服務端不會停止讀取 137 bufferedWriter.flush(); //刷新流 138 bufferedWriter.write(passwd + "\r\n"); 139 bufferedWriter.flush(); 140 if (code == 1) //注冊的話有一個邀請碼,需要多傳輸一次 141 { 142 bufferedWriter.write(inviteText.getText() + "\r\n"); 143 bufferedWriter.flush(); 144 } 145 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 146 tips = bufferedReader.readLine(); 147 if (tips.contains("管理員")) 148 { 149 isAdmin = true; 150 } 151 } catch (IOException e1) 152 { 153 new mDialog(string + "結果", "交換數據失敗!",jFrame); 154 155 } catch (NullPointerException e1) 156 { 157 new mDialog(string + "結果", "服務端關閉!請先打開服務端!",jFrame); 158 } finally 159 { 160 try 161 { 162 bufferedReader.close(); 163 bufferedWriter.close(); 164 } catch (IOException e1) 165 { 166 tips = "流關閉失敗!"; 167 new mDialog(string + "結果", tips,jFrame); 168 } 169 new mDialog(string + "結果", tips,jFrame); 170 } 171 } 172 173 174 175 176 177 public static void main(String[] args) 178 { 179 Client client = new Client(); 180 } 181 182 }
運用了Socket,並與Server交換數據。
詳細解釋不再說,注釋里有,也沒什么好說的,比較基礎的代碼。
這里有個bug沒解決(主要是沒精力也懶得改了):注冊成功后立刻點擊登錄的話會無視注冊身份,統一使用管理員身份,重啟客戶端之后正常。我似乎隱約知道是哪里的問題?

1 import com.sun.source.tree.Scope; 2 3 import java.io.*; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 import java.util.HashSet; 7 import java.util.Iterator; 8 9 public class Server 10 { 11 private Socket socket; 12 private ServerSocket serverSocket; 13 private String ipInfo; 14 private BufferedReader bufferedReader; 15 private BufferedOutputStream bufferedOutputStream; 16 private FileOutputStream fileOutputStream; 17 private String adminKey; 18 private HashSet<User> hashSet; 19 private String account, passwd, inviteCode; 20 private File infofile = new File("D://info.key"); 21 private boolean isAdmin = false; 22 23 24 public Server(String adminKey) 25 { 26 this.adminKey = adminKey; 27 try 28 { 29 serverSocket = new ServerSocket(10001); 30 while (true)//循環接受Socket 31 { 32 System.out.println("服務端開啟,等待客戶端建立連接。"); 33 socket = serverSocket.accept(); 34 ipInfo = socket.getInetAddress().getHostAddress().toString(); 35 System.out.println(ipInfo+" Connected! "); 36 new Thread(new Task(socket)).start();//並且每次接收到Socket之后,就要新建一個線程以達到多次返回數據接受數據的目的 37 } 38 } catch (IOException e) 39 { 40 e.printStackTrace(); 41 } 42 43 } 44 45 public class Task implements Runnable 46 { 47 private Socket socket; 48 49 public Task(Socket socket) 50 { 51 this.socket = socket; 52 } 53 54 @Override 55 public void run() 56 { 57 try 58 { 59 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 60 System.out.println(ipInfo); 61 String code = bufferedReader.readLine();//客戶端先發送一個標志,說明是登錄還是返回 62 if (code.equals("0")) 63 { 64 login(); 65 } 66 else 67 regist(); 68 code = bufferedReader.readLine(); 69 System.out.println(code); 70 } catch (IOException e) 71 { 72 e.printStackTrace(); 73 } 74 } 75 } 76 77 78 public void login() 79 { 80 String result; 81 String status; 82 PrintWriter printWriter = null; 83 if (isAdmin)//確定找到的用戶的身份 84 { 85 status = "管理員"; 86 } 87 else 88 89 status = "一般用戶"; 90 try 91 { 92 readFile(infofile);//先讀文件 93 account = bufferedReader.readLine();//客戶端傳回來的帳號密碼 94 passwd = bufferedReader.readLine(); 95 User user = new User(account, passwd);//封裝對象 96 if (isExists(user, false))//找到了 97 { 98 result = "登錄成功,身份:" + status;//傳回相關信息 99 } 100 else 101 { 102 result = "登錄失敗,請查驗帳號密碼!"; 103 } 104 printWriter = new PrintWriter(socket.getOutputStream(), true); 105 printWriter.println(result);//返回客戶端 106 } catch (IOException e) 107 { 108 e.printStackTrace(); 109 } 110 } 111 112 public void regist() 113 { 114 PrintWriter printWriter = null; 115 String status = null; 116 try 117 { 118 printWriter = new PrintWriter(socket.getOutputStream(), true); 119 account = bufferedReader.readLine();//客戶端傳回來的帳號密碼 120 passwd = bufferedReader.readLine(); 121 inviteCode = bufferedReader.readLine(); 122 123 User user = new User(account, passwd); 124 readFile(infofile); 125 if (!isExists(user, true)) 126 { 127 user.setAdmin(inviteCode); 128 if (user.isAdmin()) 129 { 130 status = "管理員"; 131 } 132 else 133 status = "一般用戶"; 134 135 hashSet.add(user);//沒找到就添加進Set 136 writeFile(infofile); 137 printWriter.println("注冊成功!身份:" + status); 138 } 139 else 140 { 141 printWriter.println("注冊失敗,用戶已存在!"); 142 } 143 } catch (IOException e) 144 { 145 e.printStackTrace(); 146 } 147 148 } 149 150 public void readFile(File file) 151 { 152 ObjectInputStream objectInputStream = null; 153 PrintWriter printWriter = null; 154 try 155 { 156 printWriter = new PrintWriter(socket.getOutputStream()); 157 objectInputStream = new ObjectInputStream(new FileInputStream(file));//讀取密碼文件 158 hashSet = (HashSet) objectInputStream.readObject();//信息是以hashSet的形式存放在文件中 159 } catch (IOException e) 160 { 161 if (hashSet == null) 162 { 163 hashSet = new HashSet<>();//程序第一次運行時添加進的hashMap是null,需要新實例化一個 164 writeFile(infofile);//然后再寫進去 165 } 166 } catch (ClassNotFoundException e) 167 { 168 printWriter.println("數據文件異常,請檢查文件!"); 169 } 170 } 171 172 public void writeFile(File file) 173 { 174 PrintWriter printWriter = null; 175 ObjectOutputStream objectOutputStream = null; 176 try 177 { 178 objectOutputStream = new ObjectOutputStream(new FileOutputStream(file));//對象寫入流 179 objectOutputStream.writeObject(hashSet);//將hashSet寫入文件 180 printWriter = new PrintWriter(socket.getOutputStream()); 181 } catch (IOException e) 182 { 183 printWriter.println("數據文件異常,請檢查文件!"); 184 } 185 } 186 187 public boolean isExists(User user, boolean isRegister) 188 { 189 String account = user.getAccount(); 190 String passwd = user.getPasswd(); 191 Iterator iterator = hashSet.iterator(); 192 while (iterator.hasNext()) 193 { 194 User stu = (User) iterator.next(); 195 isAdmin = stu.isAdmin(); 196 if (stu.getAccount().equals(account))//如果找到了相同用戶名 197 { 198 if (isRegister)//注冊的話 199 { 200 return true;//已經找到了 201 } 202 return stu.getPasswd().equals(passwd);//登陸的話還要比較密碼是否相同 203 } 204 } 205 return false;//沒找到就是假 206 } 207 208 209 public void setAdminKey(String string) 210 { 211 adminKey = string; 212 } 213 214 public String getAdminKey() 215 { 216 return adminKey; 217 } 218 219 public static void main(String[] args) 220 { 221 Server server = new Server("KangYh is very handsome!"); 222 223 } 224 } 225 226 class User implements Serializable 227 { 228 private String account; 229 private String passwd; 230 private boolean isAdmin = false; 231 232 public User(String account, String passwd) 233 { 234 this.account = account; 235 this.passwd = passwd; 236 } 237 238 public String getAccount() 239 { 240 return account; 241 } 242 243 public void setAccount(String account) 244 { 245 this.account = account; 246 } 247 248 public String getPasswd() 249 { 250 return passwd; 251 } 252 253 public void setPasswd(String passwd) 254 { 255 this.passwd = passwd; 256 } 257 258 public boolean isAdmin() 259 { 260 return isAdmin; 261 } 262 263 public void setAdmin(String string) 264 { 265 if (string.equals(new Server("KangYh is very handsome!").getAdminKey())) 266 { 267 isAdmin = true; 268 } 269 } 270 271 @Override 272 public int hashCode() 273 { 274 return account.hashCode() + passwd.hashCode() * 3; 275 } 276 277 @Override 278 public boolean equals(Object obj) 279 { 280 if (!(obj instanceof User)) 281 { 282 return false; 283 } 284 User user = (User) obj; 285 return account.equals(user.account); 286 } 287 }
服務端,里面有User.class。其實可以把這個class寫出來的。把User裝入HashSet<User>,保證唯一性。
這里面踩的雷就是讀寫的換行,刷新問題。寫入完畢一次必須再寫一個換行標記,否則另一頭是沒數據的。換行標記可以是
1 bufferedWriter.write(code + "\r\n"); 2 bufferedWriter.newLine();
兩者中的一種。
還有一點,序列化的對象文件,官方推薦擴展名為.ser,我用的是.obj。
放張截圖:(請無視邀請碼內容(゜ロ゜))
2.主界面
登錄成功后就是主界面了。為了省事兒,我直接截了張圖為導航的地圖。這個地圖是可以更換的。(動態更改我也不會啊(`Δ´)!)

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 import java.io.*; 6 7 8 public class Home 9 { 10 private JFrame jFrame; 11 private JPanel mapLabel; 12 private JLabel title, map; 13 private JButton admin, menu, close; 14 private Font titleFont = new Font("微軟雅黑", 1, 28); 15 private Font charFont = new Font("微軟雅黑", 1, 20); 16 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 17 18 private File pointFile = new File("D://point.obj"); 19 private File lengthFile = new File("D://length.obj"); 20 private File mapFile = new File("D://map.png"); 21 22 private boolean isAdmin = false; 23 24 public Home(boolean isAdmin) 25 { 26 this.isAdmin = isAdmin;//確定用戶身份 27 init(); 28 } 29 30 public void init() 31 { 32 jFrame = new JFrame(); 33 jFrame.setLayout(new BorderLayout()); 34 35 titleInit();//初始化標題欄 36 mapInit();//初始化地圖 37 38 jFrame.setBounds((toolkit.getScreenSize().width - 700) / 2, (toolkit.getScreenSize().height - 450) / 2, 700, 450); 39 40 JPanel buttonPanel = new JPanel(); 41 buttonPanel.setLayout(new FlowLayout()); 42 43 admin = new JButton("管理員菜單"); 44 admin.setFont(charFont); 45 admin.addMouseListener(new MouseAdapter() 46 { 47 @Override 48 public void mouseClicked(MouseEvent e) 49 { 50 new AdminMenu(); 51 } 52 }); 53 54 menu = new JButton("功能菜單"); 55 menu.setFont(charFont); 56 menu.addMouseListener(new MouseAdapter() 57 { 58 @Override 59 public void mouseClicked(MouseEvent e) 60 { 61 new NormalMenu(); 62 } 63 }); 64 buttonPanel.add(menu); 65 if (isAdmin) 66 { 67 buttonPanel.add(admin); 68 adminTips(); 69 } 70 close = new JButton("關閉"); 71 close.setFont(charFont); 72 close.addMouseListener(new MouseAdapter() 73 { 74 @Override 75 public void mouseClicked(MouseEvent e) 76 { 77 System.exit(0); 78 } 79 }); 80 buttonPanel.add(close); 81 82 jFrame.add(buttonPanel, BorderLayout.SOUTH); 83 84 jFrame.setResizable(false); 85 jFrame.setVisible(true); 86 } 87 88 public void titleInit() 89 { 90 title = new JLabel("校園導航系統", SwingConstants.CENTER); 91 title.setFont(titleFont); 92 jFrame.add(title, BorderLayout.NORTH);//標題文字 93 } 94 95 public void mapInit() 96 { 97 ImageIcon imageIcon = new ImageIcon(mapFile.getPath()); 98 imageIcon.setImage(imageIcon.getImage().getScaledInstance(imageIcon.getIconWidth(), 99 imageIcon.getIconHeight(), Image.SCALE_DEFAULT)); 100 map = new JLabel(); 101 map.setBounds(0, 0, 690, 400); 102 map.setHorizontalAlignment(0); 103 map.setIcon(imageIcon); 104 mapLabel = new JPanel(); 105 mapLabel.setSize(690, 400); 106 mapLabel.add(map); 107 jFrame.add(mapLabel, BorderLayout.CENTER);//地圖顯示 108 } 109 110 111 public void adminTips() 112 { 113 String errorTitle = "數據錯誤!"; 114 try 115 { 116 checkFile(mapFile, "地圖"); 117 } catch (IOException e) 118 { 119 e.printStackTrace(); 120 new mDialog(errorTitle, "請管理員先錄入地圖數據!", jFrame); 121 //writeMap 122 } 123 try 124 { 125 checkFile(pointFile, "景點"); 126 127 } catch (IOException e) 128 { 129 e.printStackTrace(); 130 new mDialog(errorTitle, "請管理員先錄入景點數據!", jFrame); 131 //writePoint 132 } 133 try 134 { 135 checkFile(lengthFile, "距離"); 136 137 } catch (IOException e) 138 { 139 e.printStackTrace(); 140 new mDialog(errorTitle, "請管理員先錄入距離數據!", jFrame); 141 //writeLength 142 } 143 } 144 145 public void checkFile(File file, String string) throws IOException 146 { 147 if (!file.exists() || file.length() == 0) 148 { 149 throw new IOException(string + "文件打開失敗!"); 150 } 151 } 152 153 154 }
這個沒啥坑,需要注意的是:
因為景點的數據,距離數據都是以文件的形式保存的,所以一定會有IO異常。這時候就得提供一個比較友好的提示界面,並同時將異常信息輸出到控制台上:
這個過程我,我美名其曰為“自檢”。聽着就高大上~(︶ω︶)~
然后就是主界面了。主界面的地圖我直接放了一個題目要求中的截圖。
確實比較簡陋,但是該有的都有了。
兩個界面,一個是管理員的一個是一般用戶的。

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 import java.io.BufferedReader; 6 import java.io.BufferedWriter; 7 import java.io.File; 8 9 public class AdminMenu 10 { 11 private JFrame jFrame; 12 private JButton createPoint, editPoint, deletePoint, createLength, editLength; 13 private JButton cancelButton; 14 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 15 private Font font = new Font("微軟雅黑", 1, 20); 16 private File pointFile = new File("D://point.txt"); 17 private File lengthFile = new File("D://length.txt"); 18 private JFrame childFrame; 19 private JPanel childPanel; 20 21 private BufferedReader bufferedReader; 22 private BufferedWriter bufferedWriter; 23 24 25 public AdminMenu() 26 { 27 jFrame = new JFrame("管理員菜單"); 28 jFrame.setBounds((toolkit.getScreenSize().width - 250) / 2, (toolkit.getScreenSize().height - 310) / 2, 250, 310); 29 jFrame.setLayout(new FlowLayout()); 30 31 childPanel = new JPanel(); 32 childPanel.setLayout(new FlowLayout()); 33 cancelButton = new JButton("關閉"); 34 childPanel.add(cancelButton); 35 36 37 cancelButton.addMouseListener(new MouseAdapter() 38 { 39 @Override 40 public void mouseClicked(MouseEvent e) 41 { 42 jFrame.setVisible(false); 43 } 44 }); 45 46 createPoint = new JButton("1.創建景點信息"); 47 createPoint.setFont(font); 48 createPoint.addMouseListener(new MouseAdapter() 49 { 50 @Override 51 public void mouseClicked(MouseEvent e) 52 { 53 new CreatePoint(); 54 } 55 }); 56 57 editPoint = new JButton("2.修改景點信息"); 58 editPoint.setFont(font); 59 editPoint.addMouseListener(new MouseAdapter() 60 { 61 @Override 62 public void mouseClicked(MouseEvent e) 63 { 64 new EditPoint(); 65 } 66 }); 67 68 deletePoint = new JButton("3.刪除景點信息"); 69 deletePoint.setFont(font); 70 deletePoint.addMouseListener(new MouseAdapter() 71 { 72 @Override 73 public void mouseClicked(MouseEvent e) 74 { 75 new DeletePoint(); 76 } 77 }); 78 79 createLength = new JButton("4.創建道路信息"); 80 createLength.setFont(font); 81 createLength.addMouseListener(new MouseAdapter() 82 { 83 @Override 84 public void mouseClicked(MouseEvent e) 85 { 86 new CreateLength(jFrame); 87 } 88 }); 89 90 editLength = new JButton("5.修改道路信息"); 91 editLength.setFont(font); 92 editLength.addMouseListener(new MouseAdapter() 93 { 94 @Override 95 public void mouseClicked(MouseEvent e) 96 { 97 new CreateLength(jFrame); 98 } 99 }); 100 101 jFrame.add(createPoint); 102 jFrame.add(editPoint); 103 jFrame.add(deletePoint); 104 jFrame.add(createLength); 105 jFrame.add(editLength); 106 jFrame.add(childPanel); 107 jFrame.setVisible(true); 108 } 109 110 111 }

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 6 class NormalMenu 7 { 8 9 private JFrame jFrame; 10 private JButton visitButton, searchButton, okayButton; 11 private Font font = new Font("微軟雅黑", 1, 20); 12 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 13 14 public NormalMenu() 15 { 16 jFrame = new JFrame("功能菜單"); 17 jFrame.setBounds((toolkit.getScreenSize().width - 250) / 2, (toolkit.getScreenSize().height - 200) / 2, 250, 200); 18 jFrame.setLayout(new FlowLayout()); 19 visitButton = new JButton("1.瀏覽景點信息"); 20 visitButton.setFont(font); 21 searchButton = new JButton("2.查詢最短路徑"); 22 searchButton.setFont(font); 23 okayButton = new JButton("關閉"); 24 okayButton.setFont(font); 25 26 27 visitButton.addMouseListener(new MouseAdapter() 28 { 29 @Override 30 public void mouseClicked(MouseEvent e) 31 { 32 new VisitPoint(); 33 } 34 }); 35 36 searchButton.addMouseListener(new MouseAdapter() 37 { 38 @Override 39 public void mouseClicked(MouseEvent e) 40 { 41 new SearchLength(); 42 } 43 }); 44 45 okayButton.addMouseListener(new MouseAdapter() 46 { 47 @Override 48 public void mouseClicked(MouseEvent e) 49 { 50 jFrame.setVisible(false); 51 } 52 }); 53 54 jFrame.add(visitButton); 55 jFrame.add(searchButton); 56 jFrame.add(okayButton); 57 jFrame.setResizable(false); 58 jFrame.setVisible(true); 59 60 } 61 62 }
兩個菜單的java文件。
3.管理員菜單
管理員有5個功能。
3.1創建景點信息

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 import java.io.*; 6 import java.util.TreeMap; 7 8 public class CreatePoint 9 { 10 private File file; 11 private ObjectInputStream objectInputStream; 12 private ObjectOutputStream objectOutputStream; 13 private TreeMap treeMap; 14 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 15 16 public CreatePoint() 17 { 18 try 19 { 20 file = new File("D://point.obj"); 21 objectInputStream = new ObjectInputStream(new FileInputStream(file)); 22 treeMap = (TreeMap) objectInputStream.readObject(); 23 } catch (IOException e) 24 { 25 treeMap = new TreeMap(); 26 } catch (ClassNotFoundException e) 27 { 28 }finally 29 { 30 frameInit(); 31 } 32 33 } 34 35 public void frameInit() 36 { 37 JSeparator jSeparator = new JSeparator(SwingConstants.HORIZONTAL); 38 JTextArea jTextArea = new JTextArea(15, 30); 39 JTextField jTextField = new JTextField(20); 40 41 JFrame jFrame = new JFrame(); 42 jFrame.setBounds((toolkit.getScreenSize().width - 350) / 2, (toolkit.getScreenSize().height - 450) / 2, 350, 450); 43 jFrame.setLayout(new FlowLayout()); 44 45 jFrame.add(jTextField); 46 jFrame.add(jSeparator); 47 jFrame.add(jTextArea); 48 49 JButton okayButton = new JButton("確定"); 50 JButton cancelButton = new JButton("取消"); 51 52 cancelButton.addMouseListener(new MouseAdapter() 53 { 54 @Override 55 public void mouseClicked(MouseEvent e) 56 { 57 jFrame.setVisible(false); 58 } 59 }); 60 okayButton.addMouseListener(new MouseAdapter() 61 { 62 @Override 63 public void mouseClicked(MouseEvent e) 64 { 65 treeMap.put(jTextField.getText(), jTextArea.getText()); 66 try 67 { 68 objectOutputStream = new ObjectOutputStream(new FileOutputStream(file)); 69 objectOutputStream.writeObject(treeMap); 70 new mDialog("成功", "數據正常保存", jFrame); 71 jFrame.setVisible(false); 72 } catch (IOException e1) 73 { 74 new mDialog("失敗", "數據異常!", jFrame); 75 } 76 } 77 }); 78 jFrame.add(cancelButton); 79 jFrame.add(okayButton); 80 jFrame.setVisible(true); 81 82 83 } 84 85 public static void main(String[] args) 86 { 87 new CreatePoint(); 88 } 89 90 91 }
其實可以把兩個框里的字體改一下。還有一個,每個框前面其實應該有個提示信息的。我嫌麻煩,后來有點懶得弄了。難度也不是很大,一個JLabel完事兒。
3.2 修改景點信息

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.ItemEvent; 4 import java.awt.event.ItemListener; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 import java.io.*; 8 import java.util.TreeMap; 9 import java.util.Iterator; 10 import java.util.Set; 11 12 public class EditPoint 13 { 14 private JComboBox jComboBox; 15 private String key; 16 private ObjectInputStream objectInputStream; 17 private ObjectOutputStream objectOutputStream; 18 private TreeMap treeMap; 19 private Set<String> set; 20 private File file; 21 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 22 JFrame jFrame; 23 24 public EditPoint() 25 { 26 try 27 { 28 file = new File("D://point.obj"); 29 jFrame = new JFrame(""); 30 objectInputStream = new ObjectInputStream(new FileInputStream(file)); 31 treeMap = (TreeMap) objectInputStream.readObject(); 32 set = treeMap.keySet(); 33 frameInit(); 34 } catch (IOException e) 35 { 36 new mDialog("錯誤", "沒有文件!", jFrame); 37 e.printStackTrace(); 38 } catch (ClassNotFoundException e) 39 { 40 e.printStackTrace(); 41 } 42 } 43 44 public void frameInit() 45 { 46 47 jFrame.setBounds((toolkit.getScreenSize().width - 350) / 2, (toolkit.getScreenSize().height - 450) / 2, 350, 450); 48 49 jFrame.setLayout(new FlowLayout()); 50 51 jComboBox = new JComboBox(); 52 jComboBox.setPreferredSize(new Dimension(270, 30)); 53 Iterator iterator = set.iterator(); 54 while (iterator.hasNext()) 55 { 56 jComboBox.addItem((String) iterator.next()); 57 } 58 JTextArea jTextArea = new JTextArea(15, 30); 59 jTextArea.setText((String) treeMap.get(jComboBox.getSelectedItem())); 60 61 jComboBox.addItemListener(new ItemListener() 62 { 63 @Override 64 public void itemStateChanged(ItemEvent e) 65 { 66 jTextArea.setText((String) treeMap.get(jComboBox.getSelectedItem())); 67 } 68 }); 69 JButton okayButton = new JButton("確定"); 70 JButton cancelButton = new JButton("取消"); 71 cancelButton.addMouseListener(new MouseAdapter() 72 { 73 @Override 74 public void mouseClicked(MouseEvent e) 75 { 76 jFrame.setVisible(false); 77 } 78 }); 79 okayButton.addMouseListener(new MouseAdapter() 80 { 81 @Override 82 public void mouseClicked(MouseEvent e) 83 { 84 String string = jTextArea.getText(); 85 treeMap.put((String) jComboBox.getSelectedItem(), string); 86 try 87 { 88 objectOutputStream = new ObjectOutputStream(new FileOutputStream(file)); 89 objectOutputStream.writeObject(treeMap); 90 new mDialog("成功", "數據成功修改", jFrame); 91 jFrame.setVisible(false); 92 } catch (IOException e1) 93 { 94 new mDialog("失敗", "數據異常!", jFrame); 95 } 96 97 } 98 }); 99 jFrame.add(jComboBox); 100 jFrame.add(jTextArea); 101 jFrame.add(cancelButton); 102 jFrame.add(okayButton); 103 jFrame.setResizable(false); 104 jFrame.setVisible(true); 105 } 106 107 public static void main(String[] args) 108 { 109 new EditPoint(); 110 } 111 }
3.3 刪除景點信息

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.ItemEvent; 4 import java.awt.event.ItemListener; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 import java.io.*; 8 import java.util.TreeMap; 9 import java.util.Iterator; 10 import java.util.Set; 11 12 public class DeletePoint 13 { 14 private JComboBox jComboBox; 15 private TreeMap treeMap; 16 private ObjectInputStream objectInputStream; 17 private ObjectOutputStream objectOutputStream; 18 private Set set; 19 private File file; 20 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 21 private JFrame jFrame; 22 23 public DeletePoint() 24 { 25 try 26 { 27 jFrame = new JFrame(); 28 file = new File("D://point.obj"); 29 objectInputStream = new ObjectInputStream(new FileInputStream(file)); 30 treeMap = (TreeMap) objectInputStream.readObject(); 31 frameInit(); 32 } catch (IOException e) 33 { 34 new mDialog("錯誤", "沒有文件!", jFrame); 35 e.printStackTrace(); 36 37 } catch (ClassNotFoundException e) 38 { 39 e.printStackTrace(); 40 } 41 } 42 43 public void frameInit() 44 { 45 jFrame.setLayout(new FlowLayout()); 46 jFrame.setBounds((toolkit.getScreenSize().width - 350) / 2, (toolkit.getScreenSize().height - 250) / 2, 350, 250); 47 48 jComboBox = new JComboBox(); 49 jComboBox.setPreferredSize(new Dimension(270,30));//設置大小 50 jFrame.add(jComboBox); 51 set = treeMap.keySet(); 52 Iterator iterator = set.iterator(); 53 while (iterator.hasNext()) 54 { 55 jComboBox.addItem((String) iterator.next()); 56 } 57 58 JLabel jLabel = new JLabel(); 59 jLabel.setText((String)treeMap.get(jComboBox.getSelectedItem()));//設置景點的相關信息顯示 60 jLabel.setPreferredSize(new Dimension(270,80)); 61 jFrame.add(jLabel); 62 63 JButton cancelButton = new JButton("取消"); 64 JButton okayButton = new JButton("確認"); 65 jFrame.add(cancelButton); 66 jFrame.add(okayButton); 67 68 69 jComboBox.addItemListener(new ItemListener() 70 { 71 @Override 72 public void itemStateChanged(ItemEvent e) 73 { 74 jLabel.setText((String)treeMap.get(jComboBox.getSelectedItem())); 75 } 76 }); 77 78 cancelButton.addMouseListener(new MouseAdapter() 79 { 80 @Override 81 public void mouseClicked(MouseEvent e) 82 { 83 jFrame.setVisible(false); 84 } 85 }); 86 okayButton.addMouseListener(new MouseAdapter() 87 { 88 @Override 89 public void mouseClicked(MouseEvent e) 90 { 91 try 92 { 93 treeMap.remove((String) jComboBox.getSelectedItem()); 94 95 objectOutputStream = new ObjectOutputStream(new FileOutputStream(file)); 96 objectOutputStream.writeObject(treeMap); 97 new mDialog("成功", "刪除" + (String) jComboBox.getSelectedItem() + "成功!", jFrame); 98 jLabel.setText(""); 99 jFrame.setVisible(false); 100 } catch (IOException e1) 101 { 102 new mDialog("失敗", "數據異常!", jFrame); 103 } catch (NullPointerException e1) 104 { 105 new mDialog("失敗", "已經沒有景點信息了!", jFrame);//刪到最后就變成null了,拋異常就得處理一下 106 jFrame.setVisible(false); 107 } 108 } 109 }); 110 111 jFrame.setResizable(false); 112 jFrame.setVisible(true); 113 } 114 115 public static void main(String[] args) 116 { 117 new DeletePoint(); 118 } 119 }
3.4 創建兩點間的距離信息

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.ItemEvent; 4 import java.awt.event.ItemListener; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 import java.io.*; 8 import java.util.ArrayList; 9 import java.util.Iterator; 10 import java.util.Set; 11 import java.util.TreeMap; 12 13 public class CreateLength 14 { 15 private JComboBox jComboBox1, jComboBox2; 16 private JTextField jTextField; 17 private ObjectInputStream objectInputStream1, objectInputStream2; 18 private ObjectOutputStream objectOutputStream; 19 private File lengthFile; 20 private File pointFile; 21 private double length[][]; 22 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 23 24 private TreeMap treeMap; 25 private Set set; 26 27 private LengthInfo lengthInfo; 28 private ArrayList arrayList; 29 30 public CreateLength(JFrame jFrame) 31 { 32 33 lengthFile = new File("D://length.obj"); 34 pointFile = new File("D://point.obj"); 35 try 36 { 37 objectInputStream1 = new ObjectInputStream(new FileInputStream(pointFile)); 38 } catch (IOException e) 39 { 40 new mDialog("錯誤", "沒有景點信息!", jFrame); 41 } 42 43 44 try 45 { 46 objectInputStream2 = new ObjectInputStream(new FileInputStream(lengthFile)); 47 treeMap = (TreeMap) objectInputStream1.readObject(); 48 arrayList = (ArrayList) objectInputStream2.readObject(); 49 } catch (IOException e) 50 { 51 lengthInfo = new LengthInfo(); 52 lengthInfo.init(); 53 arrayList = new ArrayList(); 54 arrayList.add(lengthInfo); 55 try 56 { 57 objectOutputStream = new ObjectOutputStream(new FileOutputStream(lengthFile)); 58 objectOutputStream.writeObject(arrayList); 59 objectOutputStream.flush(); 60 } catch (IOException e1) 61 { 62 63 } 64 } catch (ClassNotFoundException e) 65 { 66 67 } 68 69 frameInit(); 70 71 72 } 73 74 public void frameInit() 75 { 76 JFrame jFrame = new JFrame(); 77 jFrame.setLayout(new FlowLayout()); 78 jFrame.setBounds((toolkit.getScreenSize().width - 350) / 2, (toolkit.getScreenSize().height - 200) / 2, 350, 200); 79 80 jTextField = new JTextField(27); 81 jComboBox1 = new JComboBox(); 82 jComboBox1.setPreferredSize(new Dimension(270, 30)); 83 jComboBox2 = new JComboBox(); 84 jComboBox2.setPreferredSize(new Dimension(270, 30)); 85 86 set = treeMap.keySet(); 87 Iterator iterator = set.iterator(); 88 while (iterator.hasNext()) 89 { 90 String string = (String) iterator.next(); 91 jComboBox1.addItem(string); 92 jComboBox2.addItem(string); 93 } 94 95 int from = jComboBox1.getSelectedIndex(); 96 int to = jComboBox2.getSelectedIndex(); 97 98 lengthInfo = (LengthInfo) arrayList.get(0); 99 jTextField.setText(lengthInfo.getLength(from, to) + ""); 100 jComboBox1.addItemListener(new ItemListener() 101 { 102 @Override 103 public void itemStateChanged(ItemEvent e) 104 { 105 jTextField.setText(lengthInfo.getLength(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex()) + ""); 106 } 107 }); 108 jComboBox2.addItemListener(new ItemListener() 109 { 110 @Override 111 public void itemStateChanged(ItemEvent e) 112 { 113 jTextField.setText(lengthInfo.getLength(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex()) + ""); 114 } 115 }); 116 117 JButton cancelButton = new JButton("取消"); 118 JButton okayButton = new JButton("確認"); 119 120 121 cancelButton.addMouseListener(new MouseAdapter() 122 { 123 @Override 124 public void mouseClicked(MouseEvent e) 125 { 126 jFrame.setVisible(false); 127 } 128 }); 129 okayButton.addMouseListener(new MouseAdapter() 130 { 131 @Override 132 public void mouseClicked(MouseEvent e) 133 { 134 try 135 { 136 double weight = Double.parseDouble(jTextField.getText().toString()); 137 lengthInfo.editLength(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex(), weight); 138 objectOutputStream = new ObjectOutputStream(new FileOutputStream(lengthFile)); 139 objectOutputStream.writeObject(arrayList); 140 141 new mDialog("成功", "數據修改成功!", jFrame); 142 jFrame.setVisible(false); 143 } catch (NumberFormatException e1) 144 { 145 e1.printStackTrace(); 146 new mDialog("錯誤", "請輸入正確信息!", jFrame); 147 } catch (IOException e1) 148 { 149 new mDialog("錯誤", "信息寫入失敗!", jFrame); 150 } 151 152 153 } 154 }); 155 156 jFrame.add(jComboBox1); 157 jFrame.add(jComboBox2); 158 jFrame.add(jTextField); 159 jFrame.add(cancelButton); 160 jFrame.add(okayButton); 161 jFrame.setVisible(true); 162 jFrame.setResizable(false); 163 } 164 165 public static void main(String[] args) 166 { 167 new CreateLength(new JFrame()); 168 } 169 170 }
這個就要說明下了,因為當時在寫這個模塊的時候遇到了不少問題。
第一,存儲結構。
既然是選用了迪傑斯特拉算法,那么使用鄰接矩陣就是最方便的。我一開始所希望的是一個動態的二維數組,也就是ArrayList<<ArrayList<Integer>> arraylists。但是實際上操作起來會比較麻煩。最后為了趕時間還是用的普通的二維數組int length[][],長度也就固定了。這個動態的二維數組以后再研究下。
還有就是兩個JCombobox中元素的順序問題。景點信息是隨時可以更改的,所以這個JCombobox中元素的個數與順序也是個問題。怎么能保證item與鄰接矩陣中的位置精確對應?
我采取的做法,全局將景點的信息用TreeMap存儲,key為景點的名稱,value為景點的詳細信息。然后使用.ketSet()來將key存入set。因為TreeMap保存我存入的相對順序。要是用HashMap順序就亂了。
既然相對順序是固定的,那么我就不需要去鏈接鄰接矩陣與jcombobox了。只需要在改變景點信息的時候順便將鄰接矩陣中的數據改一下就行了。這樣就可以保證對應關系。
第二,數據的賦值
兩點間的距離默認應該是無限大,所以初始化的時候應該是Integer.INT_MAX。自己和自己是沒有距離的,也就是0。這些工作都應該在初始化的時候做好。
有兩點可以進行優化:一是目前的版本如果第一次輸入數據,編輯框會將初始化的值顯示在上面。其實這種情況還是留白比較好。二是既然自己跟自己沒有距離,那么兩個JCombobox就不應該出現一樣的值。
3.5 修改兩點間的距離

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.ItemEvent; 4 import java.awt.event.ItemListener; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 import java.io.*; 8 import java.util.ArrayList; 9 import java.util.Iterator; 10 import java.util.Set; 11 import java.util.TreeMap; 12 13 public class CreateLength 14 { 15 private JComboBox jComboBox1, jComboBox2; 16 private JTextField jTextField; 17 private ObjectInputStream objectInputStream1, objectInputStream2; 18 private ObjectOutputStream objectOutputStream; 19 private File lengthFile; 20 private File pointFile; 21 private double length[][]; 22 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 23 24 private TreeMap treeMap; 25 private Set set; 26 27 private LengthInfo lengthInfo; 28 private ArrayList arrayList; 29 30 public CreateLength(JFrame jFrame) 31 { 32 33 lengthFile = new File("D://length.obj"); 34 pointFile = new File("D://point.obj"); 35 try 36 { 37 objectInputStream1 = new ObjectInputStream(new FileInputStream(pointFile)); 38 } catch (IOException e) 39 { 40 new mDialog("錯誤", "沒有景點信息!", jFrame); 41 } 42 43 try 44 { 45 objectInputStream2 = new ObjectInputStream(new FileInputStream(lengthFile)); 46 treeMap = (TreeMap) objectInputStream1.readObject(); 47 arrayList = (ArrayList) objectInputStream2.readObject(); 48 } catch (IOException e) 49 { 50 lengthInfo = new LengthInfo(); 51 lengthInfo.init(); 52 arrayList = new ArrayList(); 53 arrayList.add(lengthInfo); 54 try 55 { 56 objectOutputStream = new ObjectOutputStream(new FileOutputStream(lengthFile)); 57 objectOutputStream.writeObject(arrayList); 58 objectOutputStream.flush(); 59 } catch (IOException e1) 60 { 61 62 } 63 } catch (ClassNotFoundException e) 64 { 65 66 } 67 68 frameInit(); 69 70 71 } 72 73 public void frameInit() 74 { 75 JFrame jFrame = new JFrame(); 76 jFrame.setLayout(new FlowLayout()); 77 jFrame.setBounds((toolkit.getScreenSize().width - 350) / 2, (toolkit.getScreenSize().height - 200) / 2, 350, 200); 78 79 jTextField = new JTextField(27); 80 jComboBox1 = new JComboBox(); 81 jComboBox1.setPreferredSize(new Dimension(270, 30)); 82 jComboBox2 = new JComboBox(); 83 jComboBox2.setPreferredSize(new Dimension(270, 30)); 84 85 set = treeMap.keySet(); 86 Iterator iterator = set.iterator(); 87 while (iterator.hasNext()) 88 { 89 String string = (String) iterator.next(); 90 jComboBox1.addItem(string); 91 jComboBox2.addItem(string); 92 } 93 94 int from = jComboBox1.getSelectedIndex(); 95 int to = jComboBox2.getSelectedIndex(); 96 97 lengthInfo = (LengthInfo) arrayList.get(0); 98 jTextField.setText(lengthInfo.getLength(from, to) + ""); 99 jComboBox1.addItemListener(new ItemListener() 100 { 101 @Override 102 public void itemStateChanged(ItemEvent e) 103 { 104 jTextField.setText(lengthInfo.getLength(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex()) + ""); 105 } 106 }); 107 jComboBox2.addItemListener(new ItemListener() 108 { 109 @Override 110 public void itemStateChanged(ItemEvent e) 111 { 112 jTextField.setText(lengthInfo.getLength(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex()) + ""); 113 } 114 }); 115 116 JButton cancelButton = new JButton("取消"); 117 JButton okayButton = new JButton("確認"); 118 119 120 cancelButton.addMouseListener(new MouseAdapter() 121 { 122 @Override 123 public void mouseClicked(MouseEvent e) 124 { 125 jFrame.setVisible(false); 126 } 127 }); 128 okayButton.addMouseListener(new MouseAdapter() 129 { 130 @Override 131 public void mouseClicked(MouseEvent e) 132 { 133 try 134 { 135 double weight = Double.parseDouble(jTextField.getText().toString()); 136 lengthInfo.editLength(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex(), weight); 137 objectOutputStream = new ObjectOutputStream(new FileOutputStream(lengthFile)); 138 objectOutputStream.writeObject(arrayList); 139 140 new mDialog("成功", "數據修改成功!", jFrame); 141 jFrame.setVisible(false); 142 } catch (NumberFormatException e1) 143 { 144 e1.printStackTrace(); 145 new mDialog("錯誤", "請輸入正確信息!", jFrame); 146 } catch (IOException e1) 147 { 148 new mDialog("錯誤", "信息寫入失敗!", jFrame); 149 } 150 151 152 } 153 }); 154 155 jFrame.add(jComboBox1); 156 jFrame.add(jComboBox2); 157 jFrame.add(jTextField); 158 jFrame.add(cancelButton); 159 jFrame.add(okayButton); 160 jFrame.setVisible(true); 161 jFrame.setResizable(false); 162 } 163 164 public static void main(String[] args) 165 { 166 new CreateLength(new JFrame()); 167 } 168 169 }
我承認,這個我偷懶了,這個我直接用的是上一個類。不過話說過來,這倆不是差不多嘛(´_`)
4.一般用戶的操作菜單

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 6 class NormalMenu 7 { 8 9 private JFrame jFrame; 10 private JButton visitButton, searchButton, okayButton; 11 private Font font = new Font("微軟雅黑", 1, 20); 12 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 13 14 public NormalMenu() 15 { 16 jFrame = new JFrame("功能菜單"); 17 jFrame.setBounds((toolkit.getScreenSize().width - 250) / 2, (toolkit.getScreenSize().height - 200) / 2, 250, 200); 18 jFrame.setLayout(new FlowLayout()); 19 visitButton = new JButton("1.瀏覽景點信息"); 20 visitButton.setFont(font); 21 searchButton = new JButton("2.查詢最短路徑"); 22 searchButton.setFont(font); 23 okayButton = new JButton("關閉"); 24 okayButton.setFont(font); 25 26 27 visitButton.addMouseListener(new MouseAdapter() 28 { 29 @Override 30 public void mouseClicked(MouseEvent e) 31 { 32 new VisitPoint(); 33 } 34 }); 35 36 searchButton.addMouseListener(new MouseAdapter() 37 { 38 @Override 39 public void mouseClicked(MouseEvent e) 40 { 41 new SearchLength(); 42 } 43 }); 44 45 okayButton.addMouseListener(new MouseAdapter() 46 { 47 @Override 48 public void mouseClicked(MouseEvent e) 49 { 50 jFrame.setVisible(false); 51 } 52 }); 53 54 jFrame.add(visitButton); 55 jFrame.add(searchButton); 56 jFrame.add(okayButton); 57 jFrame.setResizable(false); 58 jFrame.setVisible(true); 59 60 } 61 62 }
4.1 瀏覽景點信息

1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.ItemEvent; 4 import java.awt.event.ItemListener; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 import java.io.File; 8 import java.io.FileInputStream; 9 import java.io.IOException; 10 import java.io.ObjectInputStream; 11 import java.util.Iterator; 12 import java.util.Set; 13 import java.util.TreeMap; 14 import java.util.TreeSet; 15 16 public class VisitPoint 17 { 18 private JFrame jFrame; 19 private JComboBox jComboBox; 20 private JLabel jLabel; 21 private JButton okayButton; 22 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 23 24 private File file = new File("D://point.obj"); 25 private ObjectInputStream objectInputStream; 26 27 private TreeMap treeMap; 28 private Set set; 29 30 public VisitPoint() 31 { 32 try 33 { 34 objectInputStream = new ObjectInputStream(new FileInputStream(file)); 35 jFrame = new JFrame(); 36 } catch (IOException e) 37 { 38 new mDialog("錯誤", "無景點信息文件!", jFrame); 39 } 40 frameInit(); 41 } 42 43 public void frameInit() 44 { 45 try 46 { 47 jFrame.setLayout(new BorderLayout()); 48 jFrame.setBounds((toolkit.getScreenSize().width - 350) / 2, (toolkit.getScreenSize().height - 250) / 2, 350, 250); 49 50 } catch (Exception e) 51 { 52 e.printStackTrace(); 53 } 54 55 jComboBox = new JComboBox(); 56 jComboBox.setPreferredSize(new Dimension(270,30)); 57 try 58 { 59 treeMap = (TreeMap) objectInputStream.readObject(); 60 set = treeMap.keySet(); 61 } catch (IOException e) 62 { 63 64 } catch (ClassNotFoundException e) 65 { 66 67 } 68 Iterator iterator = set.iterator(); 69 while (iterator.hasNext()) 70 { 71 jComboBox.addItem((String) iterator.next()); 72 } 73 74 jLabel = new JLabel(); 75 jLabel.setPreferredSize(new Dimension(270,20)); 76 jLabel.setFont(new Font("宋體", 1, 20)); 77 jLabel.setText((String) treeMap.get(jComboBox.getSelectedItem())); 78 79 jComboBox.addItemListener(new ItemListener() 80 { 81 @Override 82 public void itemStateChanged(ItemEvent e) 83 { 84 jLabel.setText((String) treeMap.get(jComboBox.getSelectedItem())); 85 } 86 }); 87 88 okayButton = new JButton("確定"); 89 okayButton.setFont(new Font("微軟雅黑", 1, 20)); 90 okayButton.addMouseListener(new MouseAdapter() 91 { 92 93 @Override 94 public void mouseClicked(MouseEvent e) 95 { 96 jFrame.setVisible(false); 97 } 98 }); 99 jFrame.add(jComboBox,BorderLayout.NORTH); 100 jFrame.add(jLabel,BorderLayout.CENTER); 101 jFrame.add(okayButton,BorderLayout.SOUTH); 102 jFrame.setResizable(false); 103 jFrame.setVisible(true); 104 } 105 106 public static void main(String[] args) 107 { 108 new VisitPoint(); 109 } 110 }
很簡單,想不出啥需要強調的。
4.2 查詢任意兩點間的最短路徑

1 import javax.imageio.event.IIOReadProgressListener; 2 import javax.swing.*; 3 import java.awt.*; 4 import java.awt.event.ItemEvent; 5 import java.awt.event.ItemListener; 6 import java.awt.event.MouseAdapter; 7 import java.awt.event.MouseEvent; 8 import java.io.File; 9 import java.io.FileInputStream; 10 import java.io.IOException; 11 import java.io.ObjectInputStream; 12 import java.util.ArrayList; 13 import java.util.Iterator; 14 import java.util.Set; 15 import java.util.TreeMap; 16 17 public class SearchLength 18 { 19 private JFrame jFrame; 20 private JComboBox jComboBox1, jComboBox2; 21 private JLabel jLabel; 22 private JButton jButton; 23 24 private ObjectInputStream objectInputStream1, objectInputStream2; 25 private File lengthFile, pointFile; 26 27 private TreeMap treeMap; 28 private ArrayList arrayList; 29 private Set set; 30 31 private LengthInfo lengthInfo; 32 33 private Toolkit toolkit = Toolkit.getDefaultToolkit(); 34 35 public SearchLength() 36 { 37 38 jFrame = new JFrame(); 39 try 40 { 41 lengthFile = new File("D://length.obj"); 42 pointFile = new File("D://point.obj"); 43 objectInputStream1 = new ObjectInputStream(new FileInputStream(lengthFile)); 44 objectInputStream2 = new ObjectInputStream(new FileInputStream(pointFile)); 45 arrayList = (ArrayList) objectInputStream1.readObject(); 46 lengthInfo = (LengthInfo) arrayList.get(0); 47 48 treeMap = (TreeMap) objectInputStream2.readObject(); 49 50 51 } catch (IOException e) 52 { 53 new mDialog("錯誤", "無景點信息!", jFrame); 54 } catch (ClassNotFoundException e) 55 { 56 new mDialog("錯誤!", "文件信息錯誤!", jFrame); 57 } 58 59 60 try 61 { 62 set = treeMap.keySet(); 63 } catch (NullPointerException e) 64 { 65 new mDialog("錯誤", "無道路長度信息!", jFrame); 66 } 67 68 frameInit(); 69 } 70 71 public void frameInit() 72 { 73 jFrame.setLayout(new FlowLayout()); 74 jFrame.setBounds((toolkit.getScreenSize().width - 200) / 2, (toolkit.getScreenSize().height - 200) / 2, 400, 200); 75 76 jComboBox1 = new JComboBox(); 77 jComboBox1.setPreferredSize(new Dimension(180, 30)); 78 jComboBox1.setFont(new Font("微軟雅黑", 1, 20)); 79 jComboBox2 = new JComboBox(); 80 jComboBox2.setPreferredSize(new Dimension(180, 30)); 81 jComboBox2.setFont(new Font("微軟雅黑", 1, 20)); 82 83 Iterator iterator = set.iterator(); 84 while (iterator.hasNext()) 85 { 86 String string = (String) iterator.next(); 87 jComboBox1.addItem(string); 88 jComboBox2.addItem(string); 89 } 90 jLabel = new JLabel(); 91 jLabel.setPreferredSize(new Dimension(350, 80)); 92 jLabel.setFont(new Font("微軟雅黑", 1, 20)); 93 double str1 = lengthInfo.getMin(0, 1, treeMap); 94 jComboBox1.addItemListener(new ItemListener() 95 { 96 @Override 97 public void itemStateChanged(ItemEvent e) 98 { 99 double str1 = lengthInfo.getMin(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex(), treeMap); 100 String str2 = lengthInfo.getStringBuilder(); 101 jLabel.setText("<html><body>" + "最優路徑: " + str2 + "<br>" + "里程: " + str1 + "m" + "<body></html>"); 102 } 103 }); 104 jComboBox2.addItemListener(new ItemListener() 105 { 106 @Override 107 public void itemStateChanged(ItemEvent e) 108 { 109 double str1 = lengthInfo.getMin(jComboBox1.getSelectedIndex(), jComboBox2.getSelectedIndex(), treeMap); 110 String str2 = lengthInfo.getStringBuilder(); 111 jLabel.setText("<html><body>" + "最優路徑: " + str2 + "<br>" + "里程: " + str1 + "m" + "<body></html>"); 112 } 113 }); 114 115 jButton = new JButton("確定"); 116 jButton.addMouseListener(new MouseAdapter() 117 { 118 @Override 119 public void mouseClicked(MouseEvent e) 120 { 121 jFrame.setVisible(false); 122 } 123 }); 124 125 jFrame.add(jComboBox1); 126 jFrame.add(jComboBox2); 127 jFrame.add(jLabel); 128 jFrame.add(jButton); 129 jFrame.setResizable(false); 130 jFrame.setVisible(true); 131 } 132 133 134 }
這里面的代碼主要就是界面。實質的工作沒在這里面。
有個可以優化的:就拿上面那個圖來說,這個路徑其實是反的,因為算法最后用的是回溯,stringBuilder.append()也就是從后往前拼接的。要是正的就更好了。
還有,在JLabel中居然可以使用html的格式控制,上面的“最優路程”與“里程”的換行就是使用<br>實現的。
但是這里我有一個疑惑:字符串中的“<”“>”是顯示不出來的。一開始想使用“<--”來間隔,最后無奈只能用“---”了。
5.后記
程序不算完美,有很多我已經意識到的bug和可以繼續優化的點。但是好歹是自己的一次實踐,也是非常有價值的。
idea工程文件:
https://github.com/0-0MrLonely/SourceCode/tree/master/Java/NaviDemo