From 312655d6dd934d2a78d080976b29f4ca1eb48580 Mon Sep 17 00:00:00 2001 From: kawakami Date: Thu, 13 Feb 2020 19:50:28 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=82=AA=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=81=AE=E3=83=97=E3=83=AD=E3=83=88=E3=82=BF=E3=82=A4=E3=83=97?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 雰囲気だけ作成 ここからなるべく簡単に使えるように肉付けしていきたい 参考url http://effbot.org/tkinterbook/tkinter-dialog-windows.htm --- SerialController/Commands/CommandBase.py | 14 ++++ SerialController/GuiAssets.py | 100 +++++++++++++++++++++++ SerialController/Window.py | 11 ++- 3 files changed, 119 insertions(+), 6 deletions(-) diff --git a/SerialController/Commands/CommandBase.py b/SerialController/Commands/CommandBase.py index f8a6f769..665e4d4b 100644 --- a/SerialController/Commands/CommandBase.py +++ b/SerialController/Commands/CommandBase.py @@ -17,3 +17,17 @@ def start(self, ser, postProcess=None): @abstractclassmethod def end(self, ser): pass + + def startWithOption(self, root, ser, postProcess=None): + if self.openOptionDialog(root): + self.apply() + self.start(ser, postProcess) + return True + else: + return False + + def openOptionDialog(self, root): + return True + + def apply(self): + pass \ No newline at end of file diff --git a/SerialController/GuiAssets.py b/SerialController/GuiAssets.py index fbe5fdf9..46db977e 100644 --- a/SerialController/GuiAssets.py +++ b/SerialController/GuiAssets.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- import tkinter as tk +import tkinter.messagebox from tkinter import ttk from tkinter.scrolledtext import ScrolledText import cv2 @@ -60,6 +61,105 @@ def capture(self): def saveCapture(self): self.camera.saveCapture() +# The modal dialog +class Dialog(tk.Toplevel): + def __init__(self, parent, title = None): + tk.Toplevel.__init__(self, parent) + self.transient(parent) + + if title: + self.title(title) + + self.parent = parent + self.result = None + + body = tk.Frame(self) + self.initial_focus = self.body(body) + body.pack(padx=5, pady=5) + + self.buttonbox() + self.grab_set() + + if not self.initial_focus: + self.initial_focus = self + + self.protocol("WM_DELETE_WINDOW", self.cancel) + + self.geometry("+%d+%d" % (parent.winfo_rootx()+50, + parent.winfo_rooty()+50)) + + self.initial_focus.focus_set() + self.wait_window(self) + + # Create dialog body. return widget that should have initial focus. + # This method should be overridden. + def body(self, master): + pass + + # Add standard button box. Override if you don't want the standard buttons. + def buttonbox(self): + box = tk.Frame(self) + + w = tk.Button(box, text="OK", width=10, command=self.ok, default=tk.ACTIVE) + w.pack(side=tk.LEFT, padx=5, pady=5) + w = tk.Button(box, text="Cancel", width=10, command=self.cancel) + w.pack(side=tk.LEFT, padx=5, pady=5) + + self.bind("", self.ok) + self.bind("", self.cancel) + + box.pack() + + def ok(self, event=None): + if not self.validate(): + self.initial_focus.focus_set() # put focus back + return + + self.withdraw() + self.update_idletasks() + + self.apply() + self.cancel() + + def cancel(self, event=None): + # put focus back to the parent window + self.parent.focus_set() + self.destroy() + + def validate(self): + return 1 # override + + def apply(self): + pass # override + +class MyDialog(Dialog): + def __init__(self, parent, title = None): + super().__init__(parent, title) + + def body(self, master): + tk.Label(master, text="First:").grid(row=0) + tk.Label(master, text="Second:").grid(row=1) + + self.e1 = tk.Entry(master) + self.e2 = tk.Entry(master) + + self.e1.grid(row=0, column=1) + self.e2.grid(row=1, column=1) + return self.e1 # initial focus + + def validate(self): + try: + first = int(self.e1.get()) + second = int(self.e2.get()) + self.option = first, second + return 1 + except ValueError: + tk.messagebox.showwarning("Input Value Error", "不正な入力値です.\nPlease try again.") + return 0 + + def apply(self): + pass + # GUI of switch controller simulator class ControllerGUI: def __init__(self, root, ser): diff --git a/SerialController/Window.py b/SerialController/Window.py index 3e327b44..060e4f21 100644 --- a/SerialController/Window.py +++ b/SerialController/Window.py @@ -196,12 +196,11 @@ def startPlay(self): # 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" + if self.cur_command.startWithOption(self.root, self.ser, self.stopPlayPost): + print(self.startButton["text"] + ' ' + self.cur_command.NAME) + self.startButton["text"] = "Stop" + self.startButton["command"] = self.stopPlay + self.reloadCommandButton["state"] = "disabled" def stopPlay(self): print(self.startButton["text"] + ' ' + self.cur_command.NAME) From fb82461018cb13c6a785ea8276e8285f3ee010f8 Mon Sep 17 00:00:00 2001 From: kawakami Date: Fri, 14 Feb 2020 06:54:51 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E3=83=A9=E3=82=B8=E3=82=AA=E3=83=9C?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E8=BF=BD=E5=8A=A0=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 逆に複雑っぽい... --- .../Commands/PythonCommands/AutoRelease.py | 30 +++++++++- .../Commands/PythonCommands/Hoge.py | 48 +++++++++++++++ SerialController/GuiAssets.py | 58 ++++++++----------- SerialController/Window.py | 2 +- 4 files changed, 103 insertions(+), 35 deletions(-) create mode 100644 SerialController/Commands/PythonCommands/Hoge.py diff --git a/SerialController/Commands/PythonCommands/AutoRelease.py b/SerialController/Commands/PythonCommands/AutoRelease.py index e086463e..0e1c7ef8 100644 --- a/SerialController/Commands/PythonCommands/AutoRelease.py +++ b/SerialController/Commands/PythonCommands/AutoRelease.py @@ -3,6 +3,7 @@ from Commands.PythonCommandBase import PythonCommand, ImageProcPythonCommand from Commands.Keys import KeyPress, Button, Direction, Stick +import GuiAssets # auto releaseing pokemons class AutoRelease(ImageProcPythonCommand): @@ -47,4 +48,31 @@ def Release(self): self.press(Button.A, wait=1) self.press(Direction.UP, wait=0.2) self.press(Button.A, wait=1.5) - self.press(Button.A, wait=0.3) \ No newline at end of file + self.press(Button.A, wait=0.3) + + def openOptionDialog(self, root): + self.option = MyDialog(root, self.NAME).option + return self.option != None + + def apply(self): + print(self.option) + +class MyDialog(GuiAssets.Dialog): + def __init__(self, parent, title = None): + super().__init__(parent, title) + + def body(self, master): + frame, self.var = self.setSelectRadioButton(master, "画像認識", ["使用する", "使用しない", "テスト"]) + frame.grid(row=0) + + def validate(self): + try: + rb_var = self.var + self.option = rb_var.get(), rb_var.get() + return 1 + except ValueError: + tk.messagebox.showwarning("Input Value Error", "不正な入力値です.\nPlease try again.") + return 0 + + def apply(self): + pass \ No newline at end of file diff --git a/SerialController/Commands/PythonCommands/Hoge.py b/SerialController/Commands/PythonCommands/Hoge.py new file mode 100644 index 00000000..302df7b9 --- /dev/null +++ b/SerialController/Commands/PythonCommands/Hoge.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from Commands.PythonCommandBase import PythonCommand, ImageProcPythonCommand +from Commands.Keys import KeyPress, Button, Direction, Stick +import GuiAssets +import tkinter as tk + +class Hoge(PythonCommand): + NAME = 'hoge' + + def __init__(self): + super().__init__() + + def do(self): + while True: + self.wait(0.5) + self.press(Button.A) + + def openOptionDialog(self, root): + d = MyDialog(root, self.NAME) + return d.option != None + + def apply(self): + self.count = 0 + +class MyDialog(GuiAssets.Dialog): + def __init__(self, parent, title = None): + super().__init__(parent, title) + + def body(self, master): + frame1, self.e1 = self.setLabelWithEntry(master, "First:") + frame2, self.e2 = self.setLabelWithEntry(master, "Second:") + frame1.grid(row=0) + frame2.grid(row=1) + + def validate(self): + try: + first = int(self.e1.get()) + second = int(self.e2.get()) + self.option = first, second + return 1 + except ValueError: + tk.messagebox.showwarning("Input Value Error", "不正な入力値です.\nPlease try again.") + return 0 + + def apply(self): + pass \ No newline at end of file diff --git a/SerialController/GuiAssets.py b/SerialController/GuiAssets.py index 46db977e..3c018a96 100644 --- a/SerialController/GuiAssets.py +++ b/SerialController/GuiAssets.py @@ -62,10 +62,12 @@ def saveCapture(self): self.camera.saveCapture() # The modal dialog +# based from here: http://effbot.org/tkinterbook/tkinter-dialog-windows.htm class Dialog(tk.Toplevel): def __init__(self, parent, title = None): tk.Toplevel.__init__(self, parent) self.transient(parent) + self.option = None if title: self.title(title) @@ -77,27 +79,26 @@ def __init__(self, parent, title = None): self.initial_focus = self.body(body) body.pack(padx=5, pady=5) - self.buttonbox() - self.grab_set() + self.setButtonbox() if not self.initial_focus: self.initial_focus = self self.protocol("WM_DELETE_WINDOW", self.cancel) - self.geometry("+%d+%d" % (parent.winfo_rootx()+50, - parent.winfo_rooty()+50)) + self.geometry("+%d+%d" % (parent.winfo_rootx(), + parent.winfo_rooty())) self.initial_focus.focus_set() self.wait_window(self) - # Create dialog body. return widget that should have initial focus. + # Create dialog body that returns widget that should have initial focus. # This method should be overridden. def body(self, master): pass # Add standard button box. Override if you don't want the standard buttons. - def buttonbox(self): + def setButtonbox(self): box = tk.Frame(self) w = tk.Button(box, text="OK", width=10, command=self.ok, default=tk.ACTIVE) @@ -132,33 +133,24 @@ def validate(self): def apply(self): pass # override -class MyDialog(Dialog): - def __init__(self, parent, title = None): - super().__init__(parent, title) - - def body(self, master): - tk.Label(master, text="First:").grid(row=0) - tk.Label(master, text="Second:").grid(row=1) - - self.e1 = tk.Entry(master) - self.e2 = tk.Entry(master) - - self.e1.grid(row=0, column=1) - self.e2.grid(row=1, column=1) - return self.e1 # initial focus - - def validate(self): - try: - first = int(self.e1.get()) - second = int(self.e2.get()) - self.option = first, second - return 1 - except ValueError: - tk.messagebox.showwarning("Input Value Error", "不正な入力値です.\nPlease try again.") - return 0 - - def apply(self): - pass + ## -- Set syntax-sugars + def setLabel(self, master, text): + return tk.Label(master, text=text) + + def setLabelWithEntry(self, master, text): + frame = tk.Frame(master, relief='flat') + tk.Label(frame, text=text).grid(row=0, column=0) + entry = tk.Entry(frame) + entry.grid(row=0, column=1) + return frame, entry + + def setSelectRadioButton(self, master, text, radio_texts): + frame = tk.Frame(master, relief='flat') + tk.Label(frame, text=text).grid(row=0, column=0) + var = tk.IntVar(value=0) + for i, radio_text in enumerate(radio_texts): + tk.Radiobutton(frame, value=i, variable=var, text=radio_text).grid(row=1, column=i) + return frame, var # GUI of switch controller simulator class ControllerGUI: diff --git a/SerialController/Window.py b/SerialController/Window.py index 060e4f21..a8f040b1 100644 --- a/SerialController/Window.py +++ b/SerialController/Window.py @@ -196,7 +196,7 @@ def startPlay(self): # set and init selected command self.assignCommand() - if self.cur_command.startWithOption(self.root, self.ser, self.stopPlayPost): + if self.cur_command.startWithOption(self.lf, self.ser, self.stopPlayPost): print(self.startButton["text"] + ' ' + self.cur_command.NAME) self.startButton["text"] = "Stop" self.startButton["command"] = self.stopPlay From 5ed318da6735303c4df1288ae162de7178499b81 Mon Sep 17 00:00:00 2001 From: KawaSwitch Date: Mon, 24 Feb 2020 01:36:41 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E3=83=A9=E3=82=B8=E3=82=AA=E3=83=9C?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E3=81=AE=E8=A4=87=E6=95=B0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Commands/PythonCommands/AutoRelease.py | 25 +++++++++++-------- SerialController/GuiAssets.py | 9 ++++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/SerialController/Commands/PythonCommands/AutoRelease.py b/SerialController/Commands/PythonCommands/AutoRelease.py index 0e1c7ef8..f773cf1c 100644 --- a/SerialController/Commands/PythonCommands/AutoRelease.py +++ b/SerialController/Commands/PythonCommands/AutoRelease.py @@ -20,7 +20,7 @@ def do(self): for i in range(0, self.row): for j in range(0, self.col): - if not self.cam.isOpened(): + if not self.is_use_ir: self.Release() else: # if shiny, then skip @@ -51,28 +51,31 @@ def Release(self): self.press(Button.A, wait=0.3) def openOptionDialog(self, root): - self.option = MyDialog(root, self.NAME).option + self.option = Dialog(root, self.NAME, self.cam).option return self.option != None def apply(self): - print(self.option) + self.is_use_ir = self.option['is_use_ir'] -class MyDialog(GuiAssets.Dialog): - def __init__(self, parent, title = None): +class Dialog(GuiAssets.Dialog): + def __init__(self, parent, title, cam): + self.cam = cam super().__init__(parent, title) def body(self, master): - frame, self.var = self.setSelectRadioButton(master, "画像認識", ["使用する", "使用しない", "テスト"]) + frame = None + if self.cam.isOpened(): + frame, self.var = self.setSelectRadioButton(master, "画像認識", {1:"使用する", 0:"使用しない"}, init_var=1) + else: + frame, self.var = self.setSelectRadioButton(master, "画像認識", {0:"使用しない"}) frame.grid(row=0) def validate(self): try: - rb_var = self.var - self.option = rb_var.get(), rb_var.get() + self.option = { + 'is_use_ir': self.var.get() & self.cam.isOpened() + } return 1 except ValueError: tk.messagebox.showwarning("Input Value Error", "不正な入力値です.\nPlease try again.") return 0 - - def apply(self): - pass \ No newline at end of file diff --git a/SerialController/GuiAssets.py b/SerialController/GuiAssets.py index 3c018a96..68b4489f 100644 --- a/SerialController/GuiAssets.py +++ b/SerialController/GuiAssets.py @@ -144,12 +144,15 @@ def setLabelWithEntry(self, master, text): entry.grid(row=0, column=1) return frame, entry - def setSelectRadioButton(self, master, text, radio_texts): + def setSelectRadioButton(self, master, text, radio_pairs, init_var=0): frame = tk.Frame(master, relief='flat') tk.Label(frame, text=text).grid(row=0, column=0) + var = tk.IntVar(value=0) - for i, radio_text in enumerate(radio_texts): - tk.Radiobutton(frame, value=i, variable=var, text=radio_text).grid(row=1, column=i) + for i, (k, text) in enumerate(radio_pairs.items()): + tk.Radiobutton(frame, value=k, variable=var, text=text).grid(row=1, column=i) + var.set(init_var) + return frame, var # GUI of switch controller simulator