diff --git a/waypoint_manager/scripts/manager_GUI.py b/waypoint_manager/scripts/manager_GUI.py index ec818a2..de51c17 100755 --- a/waypoint_manager/scripts/manager_GUI.py +++ b/waypoint_manager/scripts/manager_GUI.py @@ -1,4 +1,3 @@ -from email.errors import MessageError import tkinter as tk import tkinter.filedialog import math @@ -38,7 +37,7 @@ self.bind_all("", self.menu_exit) self.edit_menu = tk.Menu(self.menu_bar, tearoff=tk.OFF) - self.edit_menu.add_command(label="Set Finish Pose", command=self.menu_move_finishpose) + self.edit_menu.add_command(label="Set Finish Pose", command=self.menu_set_finishpose) self.menu_bar.add_cascade(label="Edit", menu=self.edit_menu) self.show_menu = tk.Menu(self.menu_bar, tearoff=tk.OFF) @@ -119,9 +118,6 @@ +++++ File -> Open -> Map +++++ """ def menu_open_map(self): - if self.mymap is not None: - self.canvas.delete("all") - self.waypoints.number_dict = {} map_path = tkinter.filedialog.askopenfilename( parent=self.master, title="Select map yaml file", @@ -133,14 +129,16 @@ with open(map_path) as file: # .yamlを読み込む map_yaml = ruamel.yaml.YAML().load(file) if not "image" in map_yaml.keys(): - self.message("Selected map file is unexpected format.") + messagebox.showerror(title="Format error", message="Selected map file is unexpected format.") return try: self.mymap = MyMap(Path(map_path), map_yaml) except FileNotFoundError: - self.message("Image file is not found.") + messagebox.showerror(title="Image file is not found", message="\""+map_yaml["image"]+"\" is not found.") return self.message("Read map file " + map_path) + self.canvas.delete("all") + if self.waypoints is not None: self.waypoints.number_dict = {} ## キャンバスサイズに合わせて画像を表示 scale = 1 offset_x = 0 @@ -175,7 +173,7 @@ +++++ File -> Open -> Waypionts +++++ """ def menu_open_waypoints(self): - if self.waypoints is not None: + if (self.waypoints is not None) and (self.master.title()[0] == "*"): yn = messagebox.askyesno("Confirm", "Do you want to save changes to " + str(self.waypoints_filepath)) if yn: self.save_waypoints(str(self.waypoints_filepath)) # Yes self.canvas.delete("all") @@ -195,7 +193,7 @@ with open(filepath) as file: wp_yaml = ruamel.yaml.YAML().load(file) if (not "waypoints" in wp_yaml.keys()) or (not "finish_pose" in wp_yaml.keys()): - self.message("Selected waypoints file is unexpected format.") + messagebox.showerror(title="Format error", message="Selected waypoints file is unexpected format.") return self.waypoints = WaypointList(wp_yaml) self.finish_pose = FinishPose(wp_yaml) @@ -213,8 +211,11 @@ +++++ File -> Save +++++ """ def menu_save(self, event=None): + if not self.waypoints: return self.save_waypoints(str(self.waypoints_filepath)) self.message("Saved changes!") + title = self.master.title() + if title[0] == "*": self.master.title(title.replace("* ", "")) return @@ -222,6 +223,7 @@ +++++ File -> Save As +++++ """ def menu_saveas(self, event=None): + if not self.waypoints: return new_filepath = tkinter.filedialog.asksaveasfilename( parent=self.master, title="Save As", @@ -236,6 +238,8 @@ self.waypoints_filepath = Path(new_filepath) self.master.title(current_title.replace(old_filename, self.waypoints_filepath.name)) self.message("Save As" + "\"" + str(new_filepath) + "\"") + title = self.master.title() + if title[0] == "*": self.master.title(title.replace("* ", "")) return @@ -243,6 +247,13 @@ +++++ File -> Exit +++++ """ def menu_exit(self, event=None): + title = self.master.title() + if title[0] != "*": + self.master.destroy() + return + res = messagebox.askyesnocancel(title="Unsaved changes", message="Do you want to save changes before close?") + if res is None: return # cancel + if res == True: self.menu_save() self.master.destroy() @@ -258,7 +269,8 @@ """ +++++ Edit -> Set Finish Pose +++++ """ - def menu_move_finishpose(self, event=None): + def menu_set_finishpose(self, event=None): + if not self.waypoints: return self.message("Click any point to set finsih pose") self.setting_finish_pose = 1 return @@ -468,6 +480,8 @@ txt_box.delete(0, tk.END) txt_box.insert(tk.END, y) self.old_click_point = [event.x, event.y] + title = self.master.title() + if title[0] != "*": self.master.title("* "+title) return @@ -543,6 +557,8 @@ self.waypoints.set_waypoint_val(self.editing_waypoint_id, key, txt_box.get()) self.plot_waypoints(id=self.editing_waypoint_id) self.message("Apply changes of waypoint parameters") + title = self.master.title() + if title[0] != "*": self.master.title("* "+title) return @@ -574,6 +590,8 @@ self.canvas.delete(self.editing_waypoint_id) # ウェイポイントを示す円を削除 self.close_wp_info() self.message("Removed waypoint") + title = self.master.title() + if title[0] != "*": self.master.title("* "+title) return @@ -600,16 +618,16 @@ def add_waypoint_here(self): if (self.wp_info_win is not None) and (self.wp_info_win.winfo_exists()): self.close_wp_info() - img_xy = self.right_click_coord - if self.mymap.pil_img.getpixel((img_xy[0], img_xy[1]))[0] == 0: - self.message("There is obstacles") + img_x, img_y = self.right_click_coord + if self.mymap.pil_img.getpixel((img_x, img_y))[0] == 0: + messagebox.showwarning(title="Warning", message="There is obstacles") return # 何番目のウェイポイントの次に追加するか入力させる add_wp_win = tk.Toplevel() add_wp_win.title("Add waypoint") add_wp_win.protocol("WM_DELETE_WINDOW") add_wp_win.attributes('-topmost', True) # サブウィンドウを最前面で固定 - msg = tk.Label(add_wp_win, text="Add waypoint after no. ", font=("Consolas",15), anchor=tk.E) + msg = tk.Label(add_wp_win, text="Add new waypoint at no. ", font=("Consolas",15), anchor=tk.E) msg.grid(column=0, row=0, padx=10, pady=10, sticky=tk.EW) txt_box = tk.Entry(add_wp_win, width=4, font=("Consolas",15)) txt_box.grid(column=1, row=0, pady=10, sticky=tk.W) @@ -633,12 +651,19 @@ +++++ add waypoint hereをクリックして開いた別窓のAddボタンのコールバック +++++ """ def add_btn_callback(self, num_box: tk.Entry, win: tk.Toplevel): - prev_num = num_box.get() - if (prev_num == ""): - self.message("Please enter number") + num = num_box.get() + if (num == ""): + win.attributes('-topmost', False) + messagebox.showwarning(title="Warning", message="The number has not been entered.") + win.attributes('-topmost', True) + return + num = int(num) + if (num < 0) or (num > len(self.waypoints.waypoints)+1): + win.attributes('-topmost', False) + messagebox.showwarning(title="Warning", message="The number is out of range.") + win.attributes('-topmost', True) return win.destroy() - prev_num = int(prev_num) img_xy = self.right_click_coord # ウェイポイント座標を計算 x, y = self.mymap.image2real(img_xy[0], img_xy[1]) @@ -650,11 +675,13 @@ elif (key=="z"): point[key] = 0.0 else: point[key] = "" id = self.create_waypoint(point) - self.waypoints.insert(prev_num+1, point, id=id) + self.waypoints.insert(num, point, id=id) self.plot_waypoints(id=id) self.editing_waypoint_id = id self.canvas.itemconfig(id, fill='red') self.disp_waypoint_info(id) + title = self.master.title() + if title[0] != "*": self.master.title("* "+title) return @@ -718,7 +745,8 @@ x0, y0 = event.x, event.y img_x, img_y = self.mymap.inv_transform(x0, y0) if (img_x < 0) or (img_y < 0) or (img_x > self.mymap.width()) or (img_y > self.mymap.height()): - self.message("Click inside the map.") + retry = messagebox.askretrycancel(title="Cannot set finish pose here", message="The point is out of the map.") + if not retry: self.setting_finish_pose = 0 return x1 = x0 + math.cos(self.finish_pose.yaw) * self.point_rad * 3 y1 = y0 - math.sin(self.finish_pose.yaw) * self.point_rad * 3 @@ -746,6 +774,8 @@ self.finish_pose.yaw = theta self.setting_finish_pose = 0 self.message("New finish pose is set.") + title = self.master.title() + if title[0] != "*": self.master.title("* "+title) return @@ -848,6 +878,7 @@ self.canv_h = ch self.draw_image() return + @@ -898,7 +929,8 @@ w, h = root.winfo_screenwidth()-10, root.winfo_screenheight()-100 root.geometry("%dx%d+0+0" % (w, h)) app = Application(master=root) # tk.Frameを継承したApplicationクラスのインスタンス + root.protocol("WM_DELETE_WINDOW", app.menu_exit) try: app.mainloop() except KeyboardInterrupt as e: - app.destroy() + app.menu_exit()