Java实现的具有GUI的校园导航系统
0.写在前面
2023-3-8 更新
一直看到陆续有人star、fork,看来这个东西对有些人还是有点作用的。
这东西本来是五年前的课程设计,现在将项目独立出来了,地址Howloong/NaviGUI (github.com),有能力的自己好好优化一下吧。
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工程文件: