def createControllerWindow(self): if not self.controller is None: self.controller.focus_force() return window = tk.Toplevel(self.root) window.title('Simple Switch Controller') window.geometry("%dx%d%+d%+d" % (600, 300, 250, 125)) ttk.Button(window, text='A', command=lambda: UnitCommand.A().start(self.ser)).grid(row=5, column=11) ttk.Button(window, text='B', command=lambda: UnitCommand.B().start(self.ser)).grid(row=6, column=10) ttk.Button(window, text='X', command=lambda: UnitCommand.X().start(self.ser)).grid(row=4, column=10) ttk.Button(window, text='Y', command=lambda: UnitCommand.Y().start(self.ser)).grid(row=5, column=9) ttk.Button(window, text='L', command=lambda: UnitCommand.L().start(self.ser)).grid(row=1, column=1) ttk.Button(window, text='R', command=lambda: UnitCommand.R().start(self.ser)).grid(row=1, column=10) ttk.Button(window, text='ZL', command=lambda: UnitCommand.ZL().start(self.ser)).grid(row=0, column=1) ttk.Button(window, text='ZR', command=lambda: UnitCommand.ZR().start(self.ser)).grid(row=0, column=10) ttk.Button(window, text='MINUS', command=lambda: UnitCommand.MINUS().start(self.ser)).grid(row=3, column=3) ttk.Button(window, text='PLUS', command=lambda: UnitCommand.PLUS().start(self.ser)).grid(row=3, column=7) ttk.Button(window, text='LCLICK', command=lambda: UnitCommand.LCLICK().start(self.ser)).grid(row=4, column=1) ttk.Button(window, text='RCLICK', command=lambda: UnitCommand.RCLICK().start(self.ser)).grid(row=8, column=10) ttk.Button(window, text='HOME', command=lambda: UnitCommand.HOME().start(self.ser)).grid(row=4, column=6) ttk.Button(window, text='CAP', command=lambda: UnitCommand.CAPTURE().start(self.ser)).grid(row=4, column=4) ttk.Button(window, text='UP', command=lambda: self.unit_dir_commands[0].start(self.ser)).grid(row=6, column=1) ttk.Button(window, text='RIGHT', command=lambda: self.unit_dir_commands[1].start(self.ser)).grid(row=7, column=2) ttk.Button(window, text='DOWN', command=lambda: self.unit_dir_commands[2].start(self.ser)).grid(row=8, column=1) ttk.Button(window, text='LEFT', command=lambda: self.unit_dir_commands[3].start(self.ser)).grid(row=7, column=0) for child in window.winfo_children(): child['width'] = 8 ttk.Label(window, text='NOTE:').grid(row=9, column=0, columnspan=8, sticky='w', padx=10, pady=(20, 0)) ttk.Label(window, text='Direction buttons are toggle switch.').grid(row=10, column=0, columnspan=8, sticky='w', padx=10, pady=3) ttk.Label(window, text='Key Arrangements are based on Switch Pro. Controller.').grid(row=11, column=0, columnspan=8, sticky='w', padx=10, pady=3) # enable Keyboard as controller self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus window.bind("<FocusIn>", self.onFocusInController) window.bind("<FocusOut>", self.onFocusOutController) self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) window.protocol("WM_DELETE_WINDOW", self.closingController) self.controller = window
def createControllerWindow(self): if not self.controller is None: self.controller.focus_force() return window = ControllerGUI(self.root, self.ser) # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus if os.name == 'nt': window.bind("<FocusIn>", self.onFocusInController) window.bind("<FocusOut>", self.onFocusOutController) self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) window.protocol("WM_DELETE_WINDOW", self.closingController) self.controller = window
def activateKeyboard(self): if self.settings.is_use_keyboard.get() == True: # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus if os.name == 'nt': self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) else: if os.name == 'nt': # NOTE: Idk why but self.keyboard.stop() makes crash on Linux if not self.keyboard is None: # stop listening to keyboard events self.keyboard.stop() self.keyboard = None self.root.bind("<FocusIn>", lambda _: None) self.root.bind("<FocusOut>", lambda _: None)
def onFocusInController(self, event): # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen()
class GUI: def __init__(self): # NOTE: I'm gonna rewrite this function because this is not a good coding style self.root = tk.Tk() self.root.title('Pokemon Controller') self.frame1 = ttk.Frame(self.root, height=720, width=1280, relief='flat', borderwidth=5) self.controller = None self.keyPress = None self.keyboard = None # label frames self.lf = ttk.Labelframe(self.frame1, text='Command', padding=5) self.serial_lf = ttk.Labelframe(self.frame1, text='Serial Settings', padding=5) self.camera_lf = ttk.Labelframe(self.frame1, text='Camera', padding=5) self.control_lf = ttk.Labelframe(self.frame1, text='Controller', padding=5) # frames self.camera_f1 = ttk.Frame(self.camera_lf, relief='flat') self.camera_f2 = ttk.Frame(self.camera_lf, relief='flat') # log area self.logArea = MyScrolledText(self.frame1, width=70) self.logArea.write = self.write sys.stdout = self.logArea # load settings file self.loadSettings() # camera settings self.label1 = ttk.Label(self.camera_f1, text='Camera ID:') self.cameraID = tk.IntVar() self.cameraID.set(int(self.settings['camera_id'])) if os.name == 'nt': import clr clr.AddReference("../DirectShowLib/DirectShowLib-2005") from DirectShowLib import DsDevice, FilterCategory # Get names of detected camera devices captureDevices = DsDevice.GetDevicesOfCat( FilterCategory.VideoInputDevice) self.camera_dic = { device.Name: cam_id for cam_id, device in enumerate(captureDevices) } dev_num = len(self.camera_dic) if self.cameraID.get() > dev_num - 1: print('inappropriate camera ID! -> set to 0') self.cameraID.set(0) if dev_num == 0: print('No camera devices can be found.') # locate a combobox instead of an entry self.cameraName = tk.StringVar() self.label1['text'] = 'Camera: ' self.camera_cb = ttk.Combobox(self.camera_f1, width=30, textvariable=self.cameraName, state="readonly") self.camera_cb['values'] = [ device for device in self.camera_dic.keys() ] self.camera_cb.bind('<<ComboboxSelected>>', self.assignCamera) if not dev_num == 0: self.camera_cb.current(self.cameraID.get()) else: self.entry1 = ttk.Entry(self.camera_f1, width=5, textvariable=self.cameraID) # open up a camera self.camera = Camera() self.openCamera() if os.name == 'nt': import clr clr.AddReference("../DirectShowLib/DirectShowLib-2005") from DirectShowLib import DsDevice, FilterCategory else: pass self.showPreview = tk.BooleanVar() self.cb1 = ttk.Checkbutton(self.camera_f1, padding=5, text='Show Realtime', onvalue=True, offvalue=False, variable=self.showPreview) self.showPreview.set(True) self.label2 = ttk.Label(self.serial_lf, text='COM Port:') self.comPort = tk.IntVar() self.comPort.set(int(self.settings['com_port'])) self.entry2 = ttk.Entry(self.serial_lf, width=5, textvariable=self.comPort) self.preview = ttk.Label(self.camera_lf) # activate serial communication self.ser = Sender.Sender() self.activateSerial() self.v1 = tk.StringVar(value='Python') self.rb1 = ttk.Radiobutton(self.lf, text='Mcu', value='Mcu', variable=self.v1, command=self.setCommandCmbbox) self.rb2 = ttk.Radiobutton(self.lf, text='Python', value='Python', variable=self.v1, command=self.setCommandCmbbox) self.rb3 = ttk.Radiobutton(self.lf, text='Utility', value='Utility', variable=self.v1, command=self.setCommandCmbbox) self.reloadButton = ttk.Button(self.camera_f1, text='Reload Cam', command=self.openCamera) self.reloadComPort = ttk.Button(self.serial_lf, text='Reload Port', command=self.activateSerial) self.startButton = ttk.Button(self.lf, text='Start', command=self.startPlay) self.captureButton = ttk.Button(self.camera_f1, text='Capture', command=self.saveCapture) self.showSerial = tk.BooleanVar() self.showSerial.set(False) self.cb_show_ser = ttk.Checkbutton( self.serial_lf, padding=5, text='Show Serial', onvalue=True, offvalue=False, variable=self.showSerial, command=lambda: self.ser.setIsShowSerial(self.showSerial.get())) # simple controller self.simpleConButton = ttk.Button(self.control_lf, text='Controller', command=self.createControllerWindow) # fps self.label3 = ttk.Label(self.camera_f2, text='FPS:') self.fps = tk.StringVar() self.fps.set(str(self.settings['fps'])) self.fps_cb = ttk.Combobox(self.camera_f2, textvariable=self.fps, width=2, state="readonly") self.fps_cb['values'] = [45, 30, 15] self.fps_cb.bind('<<ComboboxSelected>>', self.applyFps) self.fps_cb.current(self.fps_cb['values'].index(self.fps.get())) # special commands registration self.unit_dir_commands = [ UnitCommand.UP(), UnitCommand.RIGHT(), UnitCommand.DOWN(), UnitCommand.LEFT(), ] self.mcu_name = tk.StringVar() self.mcu_cb = ttk.Combobox(self.lf, textvariable=self.mcu_name, state="readonly") self.mcu_cb['values'] = [name for name in McuCommand.commands.keys()] self.mcu_cb.bind('<<ComboboxSelected>>', self.assignMcuCommand) self.mcu_cb.current(0) self.py_name = tk.StringVar() self.py_cb = ttk.Combobox(self.lf, textvariable=self.py_name, state="readonly") self.py_cb['values'] = [name for name in PythonCommand.commands.keys()] self.py_cb.bind('<<ComboboxSelected>>', self.assignPythonCommand) self.py_cb.current(0) self.assignCommand() self.util_name = tk.StringVar() self.util_cb = ttk.Combobox(self.lf, textvariable=self.util_name, state="readonly") self.util_cb['values'] = [name for name in PythonCommand.utils.keys()] self.util_cb.bind('<<ComboboxSelected>>', self.assignUtilCommand) self.util_cb.current(0) self.partition1 = ttk.Label(self.camera_f1, text=' / ') self.partition2 = ttk.Label(self.camera_f1, text=' / ') self.frame1.grid(row=0, column=0, sticky='nwse') self.logArea.grid(row=0, column=7, rowspan=5, sticky='nwse') # camera self.camera_lf.grid(row=0, column=0, columnspan=3, sticky='nw') self.camera_f1.grid(row=0, column=0, sticky='nw') self.camera_f2.grid(row=2, column=0, sticky='nw', pady=(5, 0)) self.preview.grid(row=1, column=0, columnspan=7, sticky='nw') self.label1.pack(side=tk.LEFT) if os.name == 'nt': self.camera_cb.pack(side=tk.LEFT, padx=5) else: self.entry1.pack(side=tk.LEFT, padx=5) self.reloadButton.pack(side=tk.LEFT) self.partition1.pack(side=tk.LEFT, padx=10) self.cb1.pack(side=tk.LEFT) self.partition2.pack(side=tk.LEFT, padx=10) self.captureButton.pack(side=tk.LEFT) self.label3.pack(side=tk.LEFT) self.fps_cb.pack(side=tk.LEFT, padx=5) # serial self.serial_lf.grid(row=1, column=0, sticky='nw') self.label2.grid(row=0, column=0, sticky='w') self.entry2.grid(row=0, column=1, sticky='w') self.reloadComPort.grid(row=0, column=2, padx=(5, 0), sticky='w') self.cb_show_ser.grid(row=1, column=0) # controller simulator self.control_lf.grid(row=1, column=1, sticky='ne') self.simpleConButton.grid(row=0, column=0) # commands selection self.lf.grid(row=1, column=2, rowspan=3, sticky='ne') self.rb1.grid(row=0, column=0, sticky='w') self.rb2.grid(row=1, column=0, sticky='w') self.rb3.grid(row=2, column=0, sticky='w') self.setCommandCmbbox() self.startButton.grid(row=3, column=2, sticky='e') for child in self.frame1.winfo_children(): if not type(child) is ttk.Combobox: child.grid_configure(padx=5, pady=5) self.root.protocol("WM_DELETE_WINDOW", self.exit) self.doProcess() def openCamera(self): self.camera.openCamera(self.cameraID.get()) self.settings['camera_id'] = self.cameraID.get() def assignCamera(self, event): if os.name == 'nt': self.cameraID.set(self.camera_dic[self.cameraName.get()]) def loadSettings(self): self.settings = None if os.path.isfile(SETTING_PATH): self.settings = json.load(open(SETTING_PATH, 'r')) else: default = {"camera_id": 0, "com_port": 1, "fps": "45"} json.dump(default, open(SETTING_PATH, 'w'), indent=4) print('default settings file has been created') self.loadSettings() def startPlay(self): if self.cur_command is None: print('No commands have been assinged yet.') # set and init selected command self.assignCommand() print(self.startButton["text"] + ' ' + self.cur_command.getName()) self.cur_command.start(self.ser, self.stopPlayPost) self.startButton["text"] = "Stop" self.startButton["command"] = self.stopPlay def assignCommand(self): if self.v1.get() == 'Mcu': name = self.mcu_name.get() self.cur_command = McuCommand.commands[name](name) elif self.v1.get() == 'Python' or self.v1.get() == 'Utility': name = self.py_name.get() if self.v1.get( ) == 'Python' else self.util_name.get() cmd_class = PythonCommand.commands[name] if self.v1.get( ) == 'Python' else PythonCommand.utils[name] if issubclass(cmd_class, PythonCommand.ImageProcPythonCommand): self.cur_command = cmd_class(name, self.camera) else: self.cur_command = cmd_class(name) def stopPlay(self): print(self.startButton["text"] + ' ' + self.cur_command.getName()) self.startButton["state"] = "disabled" self.cur_command.end(self.ser) def stopPlayPost(self): self.startButton["text"] = "Start" self.startButton["command"] = self.startPlay self.startButton["state"] = "normal" def exit(self): if self.ser.isOpened(): self.ser.closeSerial() print("serial disconnected") # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None # save settings json.dump(self.settings, open(SETTING_PATH, 'w'), indent=4) self.camera.destroy() cv2.destroyAllWindows() self.root.destroy() def saveCapture(self): self.camera.saveCapture() def applyFps(self, event): print('changed FPS to: ' + self.fps.get() + ' [fps]') self.settings['fps'] = self.fps.get() def assignMcuCommand(self, event): print('changed to mcu command: ' + self.mcu_name.get()) def assignPythonCommand(self, event): print('changed to python command: ' + self.py_name.get()) def assignUtilCommand(self, event): print('changed to utility command: ' + self.util_name.get()) def setCommandCmbbox(self): if self.v1.get() == 'Mcu': self.mcu_cb.grid(row=1, column=1, columnspan=2, padx=(10, 0)) self.py_cb.grid_remove() self.util_cb.grid_remove() self.assignMcuCommand(None) elif self.v1.get() == 'Python': self.mcu_cb.grid_remove() self.py_cb.grid(row=1, column=1, columnspan=2, padx=(10, 0)) self.util_cb.grid_remove() self.assignPythonCommand(None) elif self.v1.get() == 'Utility': self.mcu_cb.grid_remove() self.py_cb.grid_remove() self.util_cb.grid(row=1, column=1, columnspan=2, padx=(10, 0)) self.assignUtilCommand(None) def activateSerial(self): if self.ser.isOpened(): print('Port is already opened and being closed.') self.ser.closeSerial() self.keyPress = None self.activateSerial() else: if self.ser.openSerial(self.comPort.get()): self.settings['com_port'] = self.comPort.get() print('COM Port ' + str(self.comPort.get()) + ' connected successfully') self.keyPress = KeyPress(self.ser) def createControllerWindow(self): if not self.controller is None: self.controller.focus_force() return window = ControllerGUI(self.root, self.ser) # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus if os.name == 'nt': window.bind("<FocusIn>", self.onFocusInController) window.bind("<FocusOut>", self.onFocusOutController) self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) window.protocol("WM_DELETE_WINDOW", self.closingController) self.controller = window def closingController(self): if os.name == 'nt': # NOTE: Idk why but self.keyboard.stop() makes crash on Linux # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None self.root.bind("<FocusIn>", lambda _: None) self.root.bind("<FocusOut>", lambda _: None) self.controller.destroy() self.controller = None def onFocusInController(self, event): # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() def onFocusOutController(self, event): # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None def doProcess(self): image_bgr = self.camera.readFrame() if self.showPreview.get() and image_bgr is not None: image_bgr = cv2.resize(image_bgr, (640, 360)) image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB) image_pil = Image.fromarray(image_rgb) image_tk = ImageTk.PhotoImage(image_pil) self.preview.im = image_tk self.preview['image'] = image_tk self.root.after((int)(16 * (60 / int(self.fps.get()))), self.doProcess) def write(self, str): self.logArea.insert(tk.END, str) time.sleep(0.0001) self.logArea.see(tk.END)
class GUI: def __init__(self): # NOTE: I'm gonna rewrite this function because this is not a good coding style self.root = tk.Tk() self.root.title(NAME + ' ' + VERSION) self.frame1 = ttk.Frame( self.root, height=720, width=1280, relief='flat', borderwidth=5) self.controller = None self.keyPress = None self.keyboard = None # label frames self.lf = ttk.Labelframe(self.frame1, text='Command', padding=5) self.serial_lf = ttk.Labelframe(self.frame1, text='Serial Settings', padding=5) self.camera_lf = ttk.Labelframe(self.frame1, text='Camera', padding=5) self.control_lf = ttk.Labelframe(self.frame1, text='Controller', padding=5) # frames self.camera_f1 = ttk.Frame(self.camera_lf, relief='flat') self.camera_f2 = ttk.Frame(self.camera_lf, relief='flat') self.serial_f1 = ttk.Frame(self.serial_lf, relief='flat') self.serial_f2 = ttk.Frame(self.serial_lf, relief='flat') # log area self.logArea = MyScrolledText(self.frame1, width=70) self.logArea.write = self.write sys.stdout = self.logArea # load settings file self.loadSettings() # camera settings self.label1 = ttk.Label(self.camera_f1, text='Camera ID:') self.camera_entry = None if os.name == 'nt': try: self.locateCameraCmbbox() except: # Locate an entry instead whenever dll is not imported successfully self.camera_entry = ttk.Entry(self.camera_f1, width=5, textvariable=self.settings.camera_id) else: self.camera_entry = ttk.Entry(self.camera_f1, width=5, textvariable=self.settings.camera_id) # open up a camera self.camera = Camera() self.openCamera() self.cb1 = ttk.Checkbutton( self.camera_f1, padding=5, text='Show Realtime', onvalue=True, offvalue=False, variable=self.settings.is_show_realtime) self.label2 = ttk.Label(self.serial_f1, text='COM Port:') self.entry2 = ttk.Entry(self.serial_f1, width=5, textvariable=self.settings.com_port) self.preview = CaptureArea(self.camera, self.settings.fps.get(), self.settings.is_show_realtime, self.camera_lf) # activate serial communication self.ser = Sender.Sender(self.settings.is_show_serial) self.activateSerial() self.v1 = tk.StringVar(value='Python') self.rb1 = ttk.Radiobutton(self.lf, text='Mcu', value='Mcu', variable=self.v1, command=self.setCommandCmbbox) self.rb2 = ttk.Radiobutton(self.lf, text='Python', value='Python', variable=self.v1, command=self.setCommandCmbbox) self.reloadCommandButton = ttk.Button(self.lf, text='Reload', command=self.reloadCommands) self.reloadButton = ttk.Button(self.camera_f1, text='Reload Cam', command=self.openCamera) self.reloadComPort = ttk.Button(self.serial_f1, text='Reload Port', command=self.activateSerial) self.startButton = ttk.Button(self.lf, text='Start', command=self.startPlay) self.captureButton = ttk.Button(self.camera_f1, text='Capture', command=self.preview.saveCapture) self.cb_show_ser = ttk.Checkbutton( self.serial_f2, padding=5, text='Show Serial', onvalue=True, offvalue=False, variable=self.settings.is_show_serial) # simple controller self.cb_use_keyboard = ttk.Checkbutton( self.control_lf, text='Use Keyboard', onvalue=True, offvalue=False, variable=self.settings.is_use_keyboard, command=self.activateKeyboard) self.activateKeyboard() self.simpleConButton = ttk.Button(self.control_lf, text='Controller', command=self.createControllerWindow) # fps self.label3 = ttk.Label(self.camera_f2, text='FPS:') self.fps_cb = ttk.Combobox(self.camera_f2, textvariable=self.settings.fps, width=2, state="readonly") self.fps_cb['values'] = [45, 30, 15] self.fps_cb.bind('<<ComboboxSelected>>', self.applyFps) self.fps_cb.current(self.fps_cb['values'].index(self.settings.fps.get())) # commands self.mcu_name = tk.StringVar() self.mcu_cb = ttk.Combobox(self.lf, textvariable=self.mcu_name, state="readonly") self.py_name = tk.StringVar() self.py_cb = ttk.Combobox(self.lf, textvariable=self.py_name, state="readonly") self.loadCommands() self.partition1 = ttk.Label(self.camera_f1, text=' / ') self.partition2 = ttk.Label(self.camera_f1, text=' / ') self.frame1.grid(row=0,column=0,sticky='nwse') self.logArea.grid(row=0,column=7,rowspan=5, sticky='nwse') # camera self.camera_lf.grid(row=0,column=0,columnspan=3, sticky='nw') self.camera_f1.grid(row=0,column=0, sticky='nw') self.camera_f2.grid(row=2,column=0, sticky='nw', pady=(5, 0)) self.preview.grid(row=1,column=0,columnspan=7, sticky='nw') self.label1.pack(side=tk.LEFT) self.camera_entry.pack(side=tk.LEFT, padx=5) self.reloadButton.pack(side=tk.LEFT) self.partition1.pack(side=tk.LEFT, padx=10) self.cb1.pack(side=tk.LEFT) self.partition2.pack(side=tk.LEFT, padx=10) self.captureButton.pack(side=tk.LEFT) self.label3.pack(side=tk.LEFT) self.fps_cb.pack(side=tk.LEFT, padx=5) # serial self.serial_lf.grid(row=1,column=0, sticky='nw') self.serial_f1.grid(row=0,column=0, sticky='nw') self.serial_f2.grid(row=1,column=0, sticky='nw', pady=(5, 0)) self.label2.pack(side=tk.LEFT) self.entry2.pack(side=tk.LEFT, padx=5) self.reloadComPort.pack(side=tk.LEFT) self.cb_show_ser.pack(side=tk.LEFT) # controller simulator self.control_lf.grid(row=1, column=1, sticky='ne') self.cb_use_keyboard.grid(row=0, column=0) self.simpleConButton.grid(row=1, column=0, pady=(5,0)) # commands selection self.lf.grid(row=1,column=2, rowspan=3, sticky='ne') self.rb1.grid(row=0,column=0, sticky='w') self.rb2.grid(row=1,column=0, sticky='w') self.setCommandCmbbox() self.reloadCommandButton.grid(row=3,column=1, sticky='e', pady=(10, 0)) self.startButton.grid(row=3,column=2, sticky='e', pady=(10, 0)) for child in self.frame1.winfo_children(): if not type(child) is ttk.Combobox: child.grid_configure(padx=5, pady=5) self.root.protocol("WM_DELETE_WINDOW", self.exit) self.preview.startCapture() def openCamera(self): self.camera.openCamera(self.settings.camera_id.get()) def assignCamera(self, event): if os.name == 'nt': self.settings.camera_id.set(self.camera_dic[self.cameraName.get()]) def loadSettings(self): self.settings = Settings.GuiSettings() self.settings.load() def startPlay(self): if self.cur_command is None: print('No commands have been assinged yet.') # set and init selected command self.assignCommand() print(self.startButton["text"] + ' ' + self.cur_command.NAME) self.cur_command.start(self.ser, self.stopPlayPost) self.startButton["text"] = "Stop" self.startButton["command"] = self.stopPlay self.reloadCommandButton["state"] = "disabled" def stopPlay(self): print(self.startButton["text"] + ' ' + self.cur_command.NAME) self.startButton["state"] = "disabled" self.cur_command.end(self.ser) def stopPlayPost(self): self.startButton["text"] = "Start" self.startButton["command"] = self.startPlay self.startButton["state"] = "normal" self.reloadCommandButton["state"] = "normal" def exit(self): if self.ser.isOpened(): self.ser.closeSerial() print("serial disconnected") # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None # save settings self.settings.save() self.camera.destroy() cv2.destroyAllWindows() self.root.destroy() def applyFps(self, event): print('changed FPS to: ' + self.settings.fps.get() + ' [fps]') self.preview.setFps(self.settings.fps.get()) def setCommandCmbbox(self): if self.v1.get() == 'Mcu': self.mcu_cb.grid(row=0,column=1, columnspan=2, padx=(10, 0)) self.py_cb.grid_remove() elif self.v1.get() == 'Python': self.mcu_cb.grid_remove() self.py_cb.grid(row=0,column=1, columnspan=2, padx=(10, 0)) def locateCameraCmbbox(self): import clr clr.AddReference(r"..\DirectShowLib\DirectShowLib-2005") from DirectShowLib import DsDevice, FilterCategory # Get names of detected camera devices captureDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice) self.camera_dic = {device.Name: cam_id for cam_id, device in enumerate(captureDevices)} self.camera_dic['Disable'] = max(list(self.camera_dic.values())) + 1 dev_num = len(self.camera_dic) if self.settings.camera_id.get() > dev_num - 1: print('inappropriate camera ID! -> set to 0') self.settings.camera_id.set(0) if dev_num == 0: print('No camera devices can be found.') # locate a combobox instead of an entry self.cameraName = tk.StringVar() self.label1['text'] = 'Camera: ' self.camera_entry = ttk.Combobox(self.camera_f1, width=30, textvariable=self.cameraName, state="readonly") self.camera_entry['values'] = [device for device in self.camera_dic.keys()] self.camera_entry.bind('<<ComboboxSelected>>', self.assignCamera) if not dev_num == 0: self.camera_entry.current(self.settings.camera_id.get()) def activateSerial(self): if self.ser.isOpened(): print('Port is already opened and being closed.') self.ser.closeSerial() self.keyPress = None self.activateSerial() else: if self.ser.openSerial(self.settings.com_port.get()): print('COM Port ' + str(self.settings.com_port.get()) + ' connected successfully') self.keyPress = KeyPress(self.ser) def createControllerWindow(self): if not self.controller is None: self.controller.focus_force() return window = ControllerGUI(self.root, self.ser) window.protocol("WM_DELETE_WINDOW", self.closingController) self.controller = window def activateKeyboard(self): if self.settings.is_use_keyboard.get() == True: # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus if os.name == 'nt': self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) else: if os.name == 'nt': # NOTE: Idk why but self.keyboard.stop() makes crash on Linux if not self.keyboard is None: # stop listening to keyboard events self.keyboard.stop() self.keyboard = None self.root.bind("<FocusIn>", lambda _: None) self.root.bind("<FocusOut>", lambda _: None) def closingController(self): self.controller.destroy() self.controller = None def onFocusInController(self, event): # enable Keyboard as controller if event.widget == self.root and self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() def onFocusOutController(self, event): # stop listening to keyboard events if event.widget == self.root and not self.keyboard is None: self.keyboard.stop() self.keyboard = None def write(self, str): self.logArea.insert(tk.END, str) time.sleep(0.0001) self.logArea.see(tk.END) def loadCommands(self): self.py_loader = CommandLoader(util.ospath('Commands/PythonCommands'), PythonCommandBase.PythonCommand) self.mcu_loader = CommandLoader(util.ospath('Commands/McuCommands'), McuCommandBase.McuCommand) self.py_classes = self.py_loader.load() self.mcu_classes = self.mcu_loader.load() self.setCommandItems() self.assignCommand() def setCommandItems(self): self.py_cb['values'] = [c.NAME for c in self.py_classes] self.py_cb.current(0) self.mcu_cb['values'] = [c.NAME for c in self.mcu_classes] self.mcu_cb.current(0) def assignCommand(self): if self.v1.get() == 'Mcu': self.cur_command = self.mcu_classes[self.mcu_cb.current()]() elif self.v1.get() == 'Python': cmd_class = self.py_classes[self.py_cb.current()] if issubclass(cmd_class, PythonCommandBase.ImageProcPythonCommand): self.cur_command = cmd_class(self.camera) else: self.cur_command = cmd_class() def reloadCommands(self): if self.v1.get() == 'Mcu': visibledCb = self.mcu_cb elif self.v1.get() == 'Python': visibledCb = self.py_cb oldval = visibledCb.get() self.py_classes = self.py_loader.reload() self.mcu_classes = self.mcu_loader.reload() # Restore the command selecting state if possible self.setCommandItems() if(oldval in visibledCb['values']): visibledCb.set(oldval) self.assignCommand() print('Finished reloading command modules.')
class PokeControllerApp: def __init__(self, master=None): self._logger = getLogger(__name__) self._logger.addHandler(NullHandler()) self._logger.setLevel(DEBUG) self._logger.propagate = True self.root = master self.root.title(NAME + ' ' + VERSION) # self.root.resizable(0, 0) self.controller = None self.poke_treeview = None self.keyPress = None self.keyboard = None ''' ここから ''' # build ui self.frame_1 = ttk.Frame(master) self.camera_lf = ttk.Labelframe(self.frame_1) self.label_1 = ttk.Label(self.camera_lf) self.label_1.config(anchor='center', text='Camera ID:') self.label_1.grid(padx='5', sticky='ew') self.camera_entry = ttk.Entry(self.camera_lf) self.camera_id = tk.IntVar() self.camera_entry.config(state='normal', textvariable=self.camera_id) self.camera_entry.grid(column='1', padx='5', row='0', sticky='ew') self.camera_entry.columnconfigure('1', uniform='0') self.reloadButton = ttk.Button(self.camera_lf) self.reloadButton.config(text='Reload Camera') self.reloadButton.grid(column='2', padx='5', row='0', sticky='ew') self.reloadButton.configure(command=self.openCamera) self.separator_1 = ttk.Separator(self.camera_lf) self.separator_1.config(orient='vertical') self.separator_1.grid(column='3', row='0', sticky='ns') self.cb1 = ttk.Checkbutton(self.camera_lf) self.is_show_realtime = tk.BooleanVar() self.cb1.config(text='Show Realtime', variable=self.is_show_realtime) self.cb1.grid(column='4', row='0') self.separator_2 = ttk.Separator(self.camera_lf) self.separator_2.config(orient='vertical') self.separator_2.grid(column='5', row='0', sticky='ns') self.captureButton = ttk.Button(self.camera_lf) self.captureButton.config(text='Capture') self.captureButton.grid(column='6', row='0') self.captureButton.configure(command=self.saveCapture) self.camera_f2 = ttk.Frame(self.camera_lf) self.label3 = ttk.Label(self.camera_f2) self.label3.config(text='FPS:') self.label3.grid(padx='5', sticky='ew') self.fps_cb = ttk.Combobox(self.camera_f2) self.fps = tk.StringVar() self.fps_cb.config(justify='right', state='readonly', textvariable=self.fps, values=[60, 45, 30, 15, 5]) self.fps_cb.config(width='5') self.fps_cb.grid(column='1', padx='10', row='0', sticky='ew') self.fps_cb.bind('<<ComboboxSelected>>', self.applyFps, add='') self.separator_3 = ttk.Separator(self.camera_f2) self.separator_3.config(orient='vertical') self.separator_3.grid(column='2', row='0', sticky='ns') self.show_size_label = ttk.Label(self.camera_f2) self.show_size_label.config(text='Show Size:') self.show_size_label.grid(column='3', padx='5', row='0', sticky='ew') self.show_size_cb = ttk.Combobox(self.camera_f2) self.show_size = tk.StringVar() self.show_size_cb.config(textvariable=self.show_size, state='readonly', values='640x360 1280x720 1920x1080') self.show_size_cb.grid(column='4', padx='10', row='0', sticky='ew') self.show_size_cb.bind('<<ComboboxSelected>>', self.applyWindowSize, add='') self.camera_f2.grid(column='0', columnspan='7', row='3', sticky='nsew') self.camera_name_l = ttk.Label(self.camera_lf) self.camera_name_l.config(anchor='center', text='Camera Name: ') self.camera_name_l.grid(column='0', padx='5', row='1', sticky='ew') self.Camera_Name = ttk.Combobox(self.camera_lf) self.camera_name_fromDLL = tk.StringVar() self.Camera_Name.config(state='normal', textvariable=self.camera_name_fromDLL) self.Camera_Name.grid(column='1', columnspan='6', padx='5', row='1', sticky='ew') self.Camera_Name.bind('<<ComboboxSelected>>', self.set_cameraid, add='') self.frame_1_2 = ttk.Frame(self.camera_lf) self.frame_1_2.config(height='360', relief='groove', width='640') self.frame_1_2.grid(column='0', columnspan='7', row='2') self.camera_lf.config(height='200', text='Camera', width='200') self.camera_lf.grid(columnspan='3', padx='5', sticky='ew') self.serial_lf = ttk.Labelframe(self.frame_1) self.label2 = ttk.Label(self.serial_lf) self.label2.config(text='COM Port: ') self.label2.grid(padx='5', sticky='ew') self.label2.rowconfigure('0', uniform='None', weight='0') self.entry2 = ttk.Entry(self.serial_lf) self.com_port = tk.IntVar() self.entry2.config(textvariable=self.com_port, width='5') self.entry2.grid(column='1', padx='5', row='0', sticky='ew') self.entry2.rowconfigure('0', uniform='None', weight='0') self.reloadComPort = ttk.Button(self.serial_lf) self.reloadComPort.config(text='Reload Port') self.reloadComPort.grid(column='2', row='0') self.reloadComPort.rowconfigure('0', uniform='None', weight='0') self.reloadComPort.configure(command=self.activateSerial) self.separator_4 = ttk.Separator(self.serial_lf) self.separator_4.config(orient='vertical') self.separator_4.grid(column='3', padx='5', row='0', sticky='ns') self.separator_4.rowconfigure('0', uniform='None', weight='0') self.separator_4.columnconfigure('3', uniform='None', weight='0') self.checkbutton_2 = ttk.Checkbutton(self.serial_lf) self.is_show_serial = tk.BooleanVar() self.checkbutton_2.config(text='Show Serial', variable=self.is_show_serial) self.checkbutton_2.grid(column='4', columnspan='2', padx='5', row='0', sticky='ew') self.checkbutton_2.rowconfigure('0', uniform='None', weight='0') self.serial_lf.config(text='Serial Settings') self.serial_lf.grid(column='0', columnspan='2', padx='5', row='1', sticky='nsew') self.control_lf = ttk.Labelframe(self.frame_1) self.cb_use_keyboard = ttk.Checkbutton(self.control_lf) self.cb_left_stick_mouse = ttk.Checkbutton(self.control_lf) self.cb_right_stick_mouse = ttk.Checkbutton(self.control_lf) self.is_use_keyboard = tk.BooleanVar() self.camera_lf.is_use_left_stick_mouse = tk.BooleanVar() self.camera_lf.is_use_right_stick_mouse = tk.BooleanVar() self.cb_use_keyboard.config(text='Use Keyboard', variable=self.is_use_keyboard) self.cb_use_keyboard.grid(column='0', padx='10', pady='5', sticky='ew') self.cb_use_keyboard.rowconfigure('0', weight='1') self.cb_use_keyboard.columnconfigure('0', weight='1') self.cb_use_keyboard.configure(command=self.activateKeyboard) self.cb_left_stick_mouse.config( text='Use LStick Mouse', variable=self.camera_lf.is_use_left_stick_mouse) self.cb_left_stick_mouse.grid(column='1', row='0', padx='10', pady='5', sticky='ew') self.cb_left_stick_mouse.rowconfigure('0', weight='1') self.cb_left_stick_mouse.columnconfigure('0', weight='1') self.cb_left_stick_mouse.configure( command=self.activate_Left_stick_mouse) self.cb_right_stick_mouse.config( text='Use RStick Mouse', variable=self.camera_lf.is_use_right_stick_mouse) self.cb_right_stick_mouse.grid(column='1', row='1', padx='10', pady='5', sticky='ew') self.cb_right_stick_mouse.rowconfigure('0', weight='1') self.cb_right_stick_mouse.columnconfigure('0', weight='1') self.cb_right_stick_mouse.configure( command=self.activate_Right_stick_mouse) self.simpleConButton = ttk.Button(self.control_lf) self.simpleConButton.config(text='Controller') self.simpleConButton.grid(column='0', padx='10', pady='5', row='1', sticky='ew') self.simpleConButton.rowconfigure('1', weight='1') self.simpleConButton.columnconfigure('0', weight='1') self.simpleConButton.configure(command=self.createControllerWindow) self.control_lf.config(height='200', text='Controller') # self.control_lf.grid(column='0', padx='5', row='2', sticky='nsew') self.control_lf.grid(column='0', padx='5', row='2', columnspan='2', sticky='nsew') # self.Poke_statistic_lf = ttk.Labelframe(self.frame_1) # self.OpenPokeButton = ttk.Button(self.Poke_statistic_lf) # self.OpenPokeButton.config(text='技統計') # self.OpenPokeButton.grid(padx='10', pady='10', sticky='nsew') # self.OpenPokeButton.rowconfigure('0', pad='0', uniform='1', weight='1') # self.OpenPokeButton.columnconfigure('0', pad='0', uniform='1', weight='1') # self.OpenPokeButton.configure(command=self.createGetFromHomeWindow) # self.Poke_statistic_lf.config(height='200', text='PokemonHome連携', width='200') # self.Poke_statistic_lf.grid(column='1', padx='5', row='2', sticky='nsew') self.lf = ttk.Labelframe(self.frame_1) self.Command_nb = ttk.Notebook(self.lf) self.py_cb = ttk.Combobox(self.Command_nb) self.py_name = tk.StringVar() self.py_cb.config(state='readonly', textvariable=self.py_name) self.py_cb.pack(side='top') self.Command_nb.add(self.py_cb, padding='5', text='Python Command') self.mcu_cb = ttk.Combobox(self.Command_nb) self.mcu_name = tk.StringVar() self.mcu_cb.config(state='readonly', textvariable=self.mcu_name) self.mcu_cb.pack(side='top') self.Command_nb.add(self.mcu_cb, padding='5', text='Mcu Command') self.Command_nb.grid(column='0', columnspan='2', padx='5', pady='5', row='0', sticky='ew') self.reloadCommandButton = ttk.Button(self.lf) self.reloadCommandButton.config(text='Reload') self.reloadCommandButton.grid(column='0', padx='5', pady='5', row='1', sticky='ew') self.reloadCommandButton.configure(command=self.reloadCommands) self.startButton = ttk.Button(self.lf) self.startButton.config(text='Start') self.startButton.grid(column='1', padx='5', pady='5', row='1', sticky='ew') self.startButton.configure(command=self.startPlay) self.lf.config(height='200', text='Command') self.lf.grid(column='2', padx='5', row='1', rowspan='2', sticky='nsew') self.log_scroll = ScrollbarHelper(self.frame_1, scrolltype='both') self.logArea = tk.Text(self.log_scroll.container) self.logArea.config(blockcursor='true', height='10', insertunfocussed='none', maxundo='0') self.logArea.config(relief='flat', state='disabled', undo='false', width='50') self.logArea.pack(expand='true', fill='both', side='top') self.log_scroll.add_child(self.logArea) self.log_scroll.config(borderwidth='1', padding='1', relief='sunken') # TODO - self.log_scroll: code for custom option 'usemousewheel' not implemented. self.log_scroll.grid(column='3', padx='5', pady='5', row='0', rowspan='3', sticky='nsew') self.frame_1.config(height='720', padding='5', relief='flat', width='1280') self.frame_1.pack(expand='true', fill='both', side='top') self.frame_1.columnconfigure('3', weight='1') ''' ここまで ''' # 仮置フレームを削除 self.frame_1_2.destroy() # 標準出力をログにリダイレクト sys.stdout = StdoutRedirector(self.logArea) # load settings file self.loadSettings() # 各tk変数に設定値をセット(コピペ簡単のため) self.is_show_realtime.set(self.settings.is_show_realtime.get()) self.is_show_serial.set(self.settings.is_show_serial.get()) self.is_use_keyboard.set(self.settings.is_use_keyboard.get()) self.fps.set(self.settings.fps.get()) self.show_size.set(self.settings.show_size.get()) self.com_port.set(self.settings.com_port.get()) self.camera_id.set(self.settings.camera_id.get()) # 各コンボボックスを現在の設定値に合わせて表示 self.fps_cb.current(self.fps_cb['values'].index(self.fps.get())) self.show_size_cb.current(self.show_size_cb['values'].index( self.show_size.get())) if os.name == 'nt': try: self.locateCameraCmbbox() self.camera_entry.config(state='disable') except: # Locate an entry instead whenever dll is not imported successfully self.camera_name_fromDLL.set( "An error occurred while displaying the camera names in NT environment." ) self._logger.warning( "An error occurred while displaying the camera names in NT environment." ) self.Camera_Name.config(state='disable') else: self.camera_name_fromDLL.set( "Not nt environment so that cannot show Camera name.") self.Camera_Name.config(state='disable') # open up a camera self.camera = Camera(self.fps.get()) self.openCamera() # activate serial communication self.ser = Sender.Sender(self.is_show_serial) self.activateSerial() self.activateKeyboard() self.preview = CaptureArea( self.camera, self.fps.get(), self.is_show_realtime, self.ser, self.camera_lf, *list(map(int, self.show_size.get().split("x")))) self.preview.config(cursor='crosshair') self.preview.grid(column='0', columnspan='7', row='2', padx='5', pady='5', sticky=tk.NSEW) self.loadCommands() # Main widget self.mainwindow = self.frame_1 self.root.protocol("WM_DELETE_WINDOW", self.exit) self.preview.startCapture() self.menu = PokeController_Menubar(self) self.root.config(menu=self.menu) # logging.debug(f'python version: {sys.version}') def openCamera(self): self.camera.openCamera(self.camera_id.get()) def assignCamera(self, event): if os.name == 'nt': self.camera_name_fromDLL.set(self.camera_dic[self.camera_id.get()]) def locateCameraCmbbox(self): import clr clr.AddReference(r"..\DirectShowLib\DirectShowLib-2005") from DirectShowLib import DsDevice, FilterCategory # Get names of detected camera devices captureDevices = DsDevice.GetDevicesOfCat( FilterCategory.VideoInputDevice) self.camera_dic = { cam_id: device.Name for cam_id, device in enumerate(captureDevices) } self.camera_dic[str(max(list(self.camera_dic.keys())) + 1)] = 'Disable' self.Camera_Name['values'] = [ device for device in self.camera_dic.values() ] self._logger.debug( f"Camera list: {[device for device in self.camera_dic.values()]}") dev_num = len(self.camera_dic) if self.camera_id.get() > dev_num - 1: print('Inappropriate camera ID! -> set to 0') self._logger.debug('Inappropriate camera ID! -> set to 0') self.camera_id.set(0) if dev_num == 0: print('No camera devices can be found.') self._logger.debug('No camera devices can be found.') # self.camera_entry.bind('<KeyRelease>', self.assignCamera) self.Camera_Name.current(self.camera_id.get()) def saveCapture(self): self.camera.saveCapture() def set_cameraid(self, event=None): keys = [ k for k, v in self.camera_dic.items() if v == self.Camera_Name.get() ] if keys: ret = keys[0] else: ret = None self.camera_id.set(ret) def applyFps(self, event=None): print('changed FPS to: ' + self.fps.get() + ' [fps]') self.preview.setFps(self.fps.get()) def applyWindowSize(self, event=None): width, height = map(int, self.show_size.get().split("x")) self.preview.setShowsize(height, width) def activateSerial(self): if self.ser.isOpened(): print('Port is already opened and being closed.') self.ser.closeSerial() self.keyPress = None self.activateSerial() else: if self.ser.openSerial(self.com_port.get()): print('COM Port ' + str(self.com_port.get()) + ' connected successfully') self._logger.debug('COM Port ' + str(self.com_port.get()) + ' connected successfully') self.keyPress = KeyPress(self.ser) def activateKeyboard(self): if self.is_use_keyboard.get(): # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus if os.name == 'nt': self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) else: if os.name == 'nt': # NOTE: Idk why but self.keyboard.stop() makes crash on Linux if self.keyboard is not None: # stop listening to keyboard events self.keyboard.stop() self.keyboard = None self.root.bind("<FocusIn>", lambda _: None) self.root.bind("<FocusOut>", lambda _: None) def onFocusInController(self, event): # enable Keyboard as controller if event.widget == self.root and self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() def onFocusOutController(self, event): # stop listening to keyboard events if event.widget == self.root and not self.keyboard is None: self.keyboard.stop() self.keyboard = None def createControllerWindow(self): if not self.controller is None: self.controller.focus_force() return window = ControllerGUI(self.root, self.ser) window.protocol("WM_DELETE_WINDOW", self.closingController) self.controller = window def activate_Left_stick_mouse(self): self.preview.ApplyLStickMouse() def activate_Right_stick_mouse(self): self.preview.ApplyRStickMouse() # def createGetFromHomeWindow(self): # if self.poke_treeview is not None: # self.poke_treeview.focus_force() # return # # window2 = GetFromHomeGUI(self.root, self.settings.season, self.settings.is_SingleBattle) # window2.protocol("WM_DELETE_WINDOW", self.closingGetFromHome) # self.poke_treeview = window2 def loadCommands(self): self.py_loader = CommandLoader( util.ospath('Commands/PythonCommands'), PythonCommandBase.PythonCommand) # コマンドの読み込み self.mcu_loader = CommandLoader(util.ospath('Commands/McuCommands'), McuCommandBase.McuCommand) self.py_classes = self.py_loader.load() self.mcu_classes = self.mcu_loader.load() self.setCommandItems() self.assignCommand() def setCommandItems(self): self.py_cb['values'] = [c.NAME for c in self.py_classes] self.py_cb.current(0) self.mcu_cb['values'] = [c.NAME for c in self.mcu_classes] self.mcu_cb.current(0) def assignCommand(self): # 選択されているコマンドを取得する self.mcu_cur_command = self.mcu_classes[ self.mcu_cb.current()]() # MCUコマンドについて # pythonコマンドは画像認識を使うかどうかで分岐している cmd_class = self.py_classes[self.py_cb.current()] if issubclass(cmd_class, PythonCommandBase.ImageProcPythonCommand): try: # 画像認識の際に認識位置を表示する引数追加。互換性のため従来のはexceptに。 self.py_cur_command = cmd_class(self.camera, self.preview) except TypeError: self.py_cur_command = cmd_class(self.camera) except: self.py_cur_command = cmd_class(self.camera) else: self.py_cur_command = cmd_class() if self.Command_nb.index(self.Command_nb.select()) == 0: self.cur_command = self.py_cur_command else: self.cur_command = self.mcu_cur_command def reloadCommands(self): # 表示しているタブを読み取って、どのコマンドを表示しているか取得、リロード後もそれが選択されるようにする oldval_mcu = self.mcu_cb.get() oldval_py = self.py_cb.get() self.py_classes = self.py_loader.reload() self.mcu_classes = self.mcu_loader.reload() # Restore the command selecting state if possible self.setCommandItems() if oldval_mcu in self.mcu_cb['values']: self.mcu_cb.set(oldval_mcu) if oldval_py in self.py_cb['values']: self.py_cb.set(oldval_py) self.assignCommand() print('Finished reloading command modules.') self._logger.info("Reloaded commands.") def startPlay(self): if self.cur_command is None: print('No commands have been assigned yet.') self._logger.info('No commands have been assigned yet.') # set and init selected command self.assignCommand() print(self.startButton["text"] + ' ' + self.cur_command.NAME) self._logger.info(self.startButton["text"] + ' ' + self.cur_command.NAME) self.cur_command.start(self.ser, self.stopPlayPost) self.startButton["text"] = "Stop" self.startButton["command"] = self.stopPlay self.reloadCommandButton["state"] = "disabled" def stopPlay(self): print(self.startButton["text"] + ' ' + self.cur_command.NAME) self._logger.info(self.startButton["text"] + ' ' + self.cur_command.NAME) self.startButton["state"] = "disabled" self.cur_command.end(self.ser) def stopPlayPost(self): self.startButton["text"] = "Start" self.startButton["command"] = self.startPlay self.startButton["state"] = "normal" self.reloadCommandButton["state"] = "normal" def run(self): self._logger.debug("Start Poke-Controller") self.mainwindow.mainloop() def exit(self): if self.ser.isOpened(): self.ser.closeSerial() print("Serial disconnected") # self._logger.info("Serial disconnected") # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None # save settings self.settings.is_show_realtime.set(self.is_show_realtime.get()) self.settings.is_show_serial.set(self.is_show_serial.get()) self.settings.is_use_keyboard.set(self.is_use_keyboard.get()) self.settings.fps.set(self.fps.get()) self.settings.show_size.set(self.show_size.get()) self.settings.com_port.set(self.com_port.get()) self.settings.camera_id.set(self.camera_id.get()) self.settings.save() self.camera.destroy() cv2.destroyAllWindows() self._logger.debug("Stop Poke Controller") self.root.destroy() def closingController(self): self.controller.destroy() self.controller = None # def closingGetFromHome(self): # self.poke_treeview.destroy() # self.poke_treeview = None def loadSettings(self): self.settings = Settings.GuiSettings() self.settings.load()
class GUI: def __init__(self): # NOTE: I'm gonna rewrite this function because this is not a good coding style self.root = tk.Tk() self.root.title('Pokemon Controller') self.frame1 = ttk.Frame( self.root, height=720, width=1280, relief='flat', borderwidth=5) self.controller = None self.keyPress = None self.keyboard = None # label frames self.lf = ttk.Labelframe(self.frame1, text='Command', padding=5) self.serial_lf = ttk.Labelframe(self.frame1, text='Serial Settings', padding=5) self.camera_lf = ttk.Labelframe(self.frame1, text='Camera', padding=5) self.control_lf = ttk.Labelframe(self.frame1, text='Controller', padding=5) # frames self.camera_f1 = ttk.Frame(self.camera_lf, relief='flat') self.camera_f2 = ttk.Frame(self.camera_lf, relief='flat') # log area self.logArea = MyScrolledText(self.frame1, width=70) self.logArea.write = self.write sys.stdout = self.logArea # load settings file self.loadSettings() self.label1 = ttk.Label(self.camera_f1, text='Camera ID:') self.cameraID = tk.IntVar() self.cameraID.set(int(self.settings['camera_id'])) self.entry1 = ttk.Entry(self.camera_f1, width=5, textvariable=self.cameraID) # open up a camera self.camera = Camera() self.openCamera() self.showPreview = tk.BooleanVar() self.cb1 = ttk.Checkbutton( self.camera_f1, padding=5, text='Show Realtime', onvalue=True, offvalue=False, variable=self.showPreview) self.showPreview.set(True) self.label2 = ttk.Label(self.serial_lf, text='COM Port:') self.comPort = tk.IntVar() self.comPort.set(int(self.settings['com_port'])) self.entry2 = ttk.Entry(self.serial_lf, width=5, textvariable=self.comPort) self.preview = ttk.Label(self.camera_lf) # activate serial communication self.ser = Sender.Sender() self.activateSerial() self.v1 = tk.StringVar(value='Python') self.rb1 = ttk.Radiobutton(self.lf, text='Mcu', value='Mcu', variable=self.v1, command=self.setCommandCmbbox) self.rb2 = ttk.Radiobutton(self.lf, text='Python', value='Python', variable=self.v1, command=self.setCommandCmbbox) self.rb3 = ttk.Radiobutton(self.lf, text='Utility', value='Utility', variable=self.v1, command=self.setCommandCmbbox) self.reloadButton = ttk.Button(self.camera_f1, text='Reload Cam', command=self.openCamera) self.reloadComPort = ttk.Button(self.serial_lf, text='Reload Port', command=self.activateSerial) self.startButton = ttk.Button(self.lf, text='Start', command=self.startPlay) self.captureButton = ttk.Button(self.camera_f1, text='Capture', command=self.saveCapture) self.showSerial = tk.BooleanVar() self.showSerial.set(False) self.cb_show_ser = ttk.Checkbutton( self.serial_lf, padding=5, text='Show Serial', onvalue=True, offvalue=False, variable=self.showSerial, command=lambda: self.ser.setIsShowSerial(self.showSerial.get())) # simple controller self.simpleConButton = ttk.Button(self.control_lf, text='Controller', command=self.createControllerWindow) # fps self.label3 = ttk.Label(self.camera_f2, text='FPS:') self.fps = tk.StringVar() self.fps.set(str(self.settings['fps'])) self.fps_cb = ttk.Combobox(self.camera_f2, textvariable=self.fps, width=2, state="readonly") self.fps_cb['values'] = [45, 30, 15] self.fps_cb.bind('<<ComboboxSelected>>', self.applyFps) self.fps_cb.current(self.fps_cb['values'].index(self.fps.get())) # special commands registration self.unit_dir_commands = [ UnitCommand.UP(), UnitCommand.RIGHT(), UnitCommand.DOWN(), UnitCommand.LEFT(), ] self.mcu_name = tk.StringVar() self.mcu_cb = ttk.Combobox(self.lf, textvariable=self.mcu_name, state="readonly") self.mcu_cb['values'] = [name for name in McuCommand.commands.keys()] self.mcu_cb.bind('<<ComboboxSelected>>', self.assignMcuCommand) self.mcu_cb.current(0) self.py_name = tk.StringVar() self.py_cb = ttk.Combobox(self.lf, textvariable=self.py_name, state="readonly") self.py_cb['values'] = [name for name in PythonCommand.commands.keys()] self.py_cb.bind('<<ComboboxSelected>>', self.assignPythonCommand) self.py_cb.current(0) self.assignCommand() self.util_name = tk.StringVar() self.util_cb = ttk.Combobox(self.lf, textvariable=self.util_name, state="readonly") self.util_cb['values'] = [name for name in PythonCommand.utils.keys()] self.util_cb.bind('<<ComboboxSelected>>', self.assignUtilCommand) self.util_cb.current(0) self.partition1 = ttk.Label(self.camera_f1, text=' / ') self.partition2 = ttk.Label(self.camera_f1, text=' / ') self.frame1.grid(row=0,column=0,sticky='nwse') self.logArea.grid(row=0,column=7,rowspan=5, sticky='nwse') # camera self.camera_lf.grid(row=0,column=0,columnspan=3, sticky='nw') self.camera_f1.grid(row=0,column=0, sticky='nw') self.camera_f2.grid(row=2,column=0, sticky='nw', pady=(5, 0)) self.preview.grid(row=1,column=0,columnspan=7, sticky='nw') self.label1.pack(side=tk.LEFT) self.entry1.pack(side=tk.LEFT, padx=5) self.reloadButton.pack(side=tk.LEFT) self.partition1.pack(side=tk.LEFT, padx=10) self.cb1.pack(side=tk.LEFT) self.partition2.pack(side=tk.LEFT, padx=10) self.captureButton.pack(side=tk.LEFT) self.label3.pack(side=tk.LEFT) self.fps_cb.pack(side=tk.LEFT, padx=5) # serial self.serial_lf.grid(row=1,column=0, sticky='nw') self.label2.grid(row=0,column=0, sticky='w') self.entry2.grid(row=0,column=1, sticky='w') self.reloadComPort.grid(row=0,column=2, padx=(5,0), sticky='w') self.cb_show_ser.grid(row=1, column=0) # controller simulator self.control_lf.grid(row=1, column=1, sticky='ne') self.simpleConButton.grid(row=0, column=0) # commands selection self.lf.grid(row=1,column=2, rowspan=3, sticky='ne') self.rb1.grid(row=0,column=0, sticky='w') self.rb2.grid(row=1,column=0, sticky='w') self.rb3.grid(row=2,column=0, sticky='w') self.setCommandCmbbox() self.startButton.grid(row=3,column=2, sticky='e') for child in self.frame1.winfo_children(): if not type(child) is ttk.Combobox: child.grid_configure(padx=5, pady=5) self.root.iconbitmap('../infinite.ico') self.root.protocol("WM_DELETE_WINDOW", self.exit) self.root.after(100, self.doProcess) def openCamera(self): self.camera.openCamera(self.cameraID.get()) self.settings['camera_id'] = self.cameraID.get() def loadSettings(self): self.settings = None if os.path.isfile(SETTING_PATH): self.settings = json.load(open(SETTING_PATH, 'r')) else: default = { "camera_id": 0, "com_port": 1, "fps": "45" } json.dump(default, open(SETTING_PATH, 'w'), indent=4) print('default settings file has been created') self.loadSettings() def startPlay(self): if self.cur_command is None: print('No commands have been assinged yet.') # set and init selected command self.assignCommand() print(self.startButton["text"] + ' ' + self.cur_command.getName()) self.cur_command.start(self.ser, self.stopPlayPost) self.startButton["text"] = "Stop" self.startButton["command"] = self.stopPlay def assignCommand(self): if self.v1.get() == 'Mcu': name = self.mcu_name.get() self.cur_command = McuCommand.commands[name](name) elif self.v1.get() == 'Python' or self.v1.get() == 'Utility': name = self.py_name.get() if self.v1.get() == 'Python' else self.util_name.get() cmd_class = PythonCommand.commands[name] if self.v1.get() == 'Python' else PythonCommand.utils[name] if issubclass(cmd_class, PythonCommand.ImageProcPythonCommand): self.cur_command = cmd_class(name, self.camera) else: self.cur_command = cmd_class(name) def stopPlay(self): print(self.startButton["text"] + ' ' + self.cur_command.getName()) self.startButton["state"] = "disabled" self.cur_command.end(self.ser) def stopPlayPost(self): self.startButton["text"] = "Start" self.startButton["command"] = self.startPlay self.startButton["state"] = "normal" def exit(self): if self.ser.isOpened(): self.ser.closeSerial() print("serial disconnected") # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None # save settings json.dump(self.settings, open(SETTING_PATH, 'w'), indent=4) self.root.destroy() def saveCapture(self): self.camera.saveCapture() def applyFps(self, event): print('changed FPS to: ' + self.fps.get() + ' [fps]') self.settings['fps'] = self.fps.get() def assignMcuCommand(self, event): print('changed to mcu command: ' + self.mcu_name.get()) def assignPythonCommand(self, event): print('changed to python command: ' + self.py_name.get()) def assignUtilCommand(self, event): print('changed to utility command: ' + self.util_name.get()) def setCommandCmbbox(self): if self.v1.get() == 'Mcu': self.mcu_cb.grid(row=1,column=1, columnspan=2, padx=(10, 0)) self.py_cb.grid_remove() self.util_cb.grid_remove() self.assignMcuCommand(None) elif self.v1.get() == 'Python': self.mcu_cb.grid_remove() self.py_cb.grid(row=1,column=1, columnspan=2, padx=(10, 0)) self.util_cb.grid_remove() self.assignPythonCommand(None) elif self.v1.get() == 'Utility': self.mcu_cb.grid_remove() self.py_cb.grid_remove() self.util_cb.grid(row=1,column=1, columnspan=2, padx=(10, 0)) self.assignUtilCommand(None) def activateSerial(self): try: if self.ser.isOpened(): print('Port is already opened and being closed.') self.ser.closeSerial() self.keyPress = None self.activateSerial() else: self.ser.openSerial("COM"+str(self.comPort.get())) self.settings['com_port'] = self.comPort.get() print('COM Port ' + str(self.comPort.get()) + ' connected successfully') self.keyPress = KeyPress(self.ser) except IOError: print('COM Port: can\'t be established') def createControllerWindow(self): if not self.controller is None: self.controller.focus_force() return window = tk.Toplevel(self.root) window.title('Simple Switch Controller') window.geometry("%dx%d%+d%+d" % (600, 300, 250, 125)) ttk.Button(window, text='A', command=lambda: UnitCommand.A().start(self.ser)).grid(row=5, column=11) ttk.Button(window, text='B', command=lambda: UnitCommand.B().start(self.ser)).grid(row=6, column=10) ttk.Button(window, text='X', command=lambda: UnitCommand.X().start(self.ser)).grid(row=4, column=10) ttk.Button(window, text='Y', command=lambda: UnitCommand.Y().start(self.ser)).grid(row=5, column=9) ttk.Button(window, text='L', command=lambda: UnitCommand.L().start(self.ser)).grid(row=1, column=1) ttk.Button(window, text='R', command=lambda: UnitCommand.R().start(self.ser)).grid(row=1, column=10) ttk.Button(window, text='ZL', command=lambda: UnitCommand.ZL().start(self.ser)).grid(row=0, column=1) ttk.Button(window, text='ZR', command=lambda: UnitCommand.ZR().start(self.ser)).grid(row=0, column=10) ttk.Button(window, text='MINUS', command=lambda: UnitCommand.MINUS().start(self.ser)).grid(row=3, column=3) ttk.Button(window, text='PLUS', command=lambda: UnitCommand.PLUS().start(self.ser)).grid(row=3, column=7) ttk.Button(window, text='LCLICK', command=lambda: UnitCommand.LCLICK().start(self.ser)).grid(row=4, column=1) ttk.Button(window, text='RCLICK', command=lambda: UnitCommand.RCLICK().start(self.ser)).grid(row=8, column=10) ttk.Button(window, text='HOME', command=lambda: UnitCommand.HOME().start(self.ser)).grid(row=4, column=6) ttk.Button(window, text='CAP', command=lambda: UnitCommand.CAPTURE().start(self.ser)).grid(row=4, column=4) ttk.Button(window, text='UP', command=lambda: self.unit_dir_commands[0].start(self.ser)).grid(row=6, column=1) ttk.Button(window, text='RIGHT', command=lambda: self.unit_dir_commands[1].start(self.ser)).grid(row=7, column=2) ttk.Button(window, text='DOWN', command=lambda: self.unit_dir_commands[2].start(self.ser)).grid(row=8, column=1) ttk.Button(window, text='LEFT', command=lambda: self.unit_dir_commands[3].start(self.ser)).grid(row=7, column=0) for child in window.winfo_children(): child['width'] = 8 ttk.Label(window, text='NOTE:').grid(row=9, column=0, columnspan=8, sticky='w', padx=10, pady=(20, 0)) ttk.Label(window, text='Direction buttons are toggle switch.').grid(row=10, column=0, columnspan=8, sticky='w', padx=10, pady=3) ttk.Label(window, text='Key Arrangements are based on Switch Pro. Controller.').grid(row=11, column=0, columnspan=8, sticky='w', padx=10, pady=3) # enable Keyboard as controller self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() # bind focus window.bind("<FocusIn>", self.onFocusInController) window.bind("<FocusOut>", self.onFocusOutController) self.root.bind("<FocusIn>", self.onFocusInController) self.root.bind("<FocusOut>", self.onFocusOutController) window.protocol("WM_DELETE_WINDOW", self.closingController) self.controller = window def closingController(self): # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None self.root.bind("<FocusIn>", lambda _: None) self.root.bind("<FocusOut>", lambda _: None) self.controller.destroy() self.controller = None def onFocusInController(self, event): # enable Keyboard as controller if self.keyboard is None: self.keyboard = SwitchKeyboardController(self.keyPress) self.keyboard.listen() def onFocusOutController(self, event): # stop listening to keyboard events if not self.keyboard is None: self.keyboard.stop() self.keyboard = None def doProcess(self): image_bgr = self.camera.readFrame() if self.showPreview.get() and image_bgr is not None: image_bgr = cv2.resize(image_bgr, (640, 360)) image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB) image_pil = Image.fromarray(image_rgb) image_tk = ImageTk.PhotoImage(image_pil) self.preview.im = image_tk self.preview['image']=image_tk self.root.after((int)(16 * (60 / int(self.fps.get()))), self.doProcess) def write(self, str): self.logArea.insert(tk.END, str) time.sleep(0.0001) self.logArea.see(tk.END)