class LabeledVerticalScale(Frame): """ LabeledVerticalScale - Supporting Frame of vertical slider with labels """ def __init__(self, parent, text="", value=0.0, slider_bind_func=None): Frame.__init__(self, parent) self.main_bg = parent['bg'] self.config(bg=self.main_bg) self.slider_events = ["<ButtonRelease-1>", "<ButtonRelease-3>"] self.label = Label(self, text=text) self.label.grid(row=0, column=0, padx=5, pady=3, sticky='s') self.slider = Scale(self, from_=1, to=0, orient=VERTICAL, resolution=0.01, length=200, width=18) self.slider.grid(row=1, column=0, padx=5, pady=5, sticky='n') if slider_bind_func is not None: for event in self.slider_events: self.slider.bind(event, slider_bind_func) self.slider.set(value) self.label.config(bg=self.slider['bg']) def get(self): return self.slider.get()
def ShowClock(self): self.SetServerTimeOffset() clockwindow = tix.Toplevel() clockwindow.resizable(0,0) tix.Label(clockwindow, text="현재 보인아이 시간").pack() clocklabel = Label(clockwindow, text="00:00:00", font=("TkDefaultFont", 50, "bold")) clocklabel.pack(expand=YES, fill=BOTH) clockwindow.update_idletasks() fontscale = Scale(clockwindow,label="글자크기",from_=10, to=200, orient=HORIZONTAL, resolution=10) fontscale.pack(fill=Y,anchor=S) fontscale.set(50) fontscale.bind("<ButtonRelease-1>",lambda x: self.UpdateStandaloneClock(clocklabel, fontscale)) clocklabel.after(100, self.UpdateBoiniClock(clocklabel))
def __init__(self, modelProc, tick): self.modelProc = modelProc self.tick = tick self.queue = modelProc.getQueue() # ----------------- Model parameters ----------------- # Waiting time between two events self.refreshRate = DEFAULT_REFRESH_RATE # Elapsed time (in number of ticks) self.count = 0 # ------------------------ GUI ----------------------- # Main window self.window = Tk() self.window.title("Model Rendering") self.window.configure(bg=BG_COLOR) self.window.protocol("WM_DELETE_WINDOW", self.onClosing) # Main pane mainPane = PanedWindow(self.window, orient=HORIZONTAL, bg=BG_COLOR) mainPane.pack(side=TOP, expand=Y, fill=BOTH, pady=5, padx=5) # Canvas frame canvasFrame = LabelFrame(mainPane, text="Rendering", padx=10, pady=10, bg=BG_COLOR) mainPane.add(canvasFrame) self.canvas = Canvas(canvasFrame, width=CANVAS_X, height=CANVAS_Y, background="white") self.canvas.pack() # Parameters frame paramFrame = LabelFrame(mainPane, text="Simulation parameters",\ padx=20, pady=20, bg=BG_COLOR) mainPane.add(paramFrame) # ===> Refresh rate slider self.stepVar = DoubleVar(paramFrame, value=DEFAULT_REFRESH_RATE) slider = Scale(paramFrame, from_=0, to_=0.5, resolution=0.001, length=350, orient=VERTICAL,\ variable=self.stepVar, label="# Refresh rate", bg=BG_COLOR, bd=1) slider.bind("<ButtonRelease-1>", self.updateRate) slider.grid(row=1, column=1) # ===> Elapsed time self.timeLabel = Label(paramFrame, text="# Elapsed time (hours) :\n0", bg=BG_COLOR) self.timeLabel.grid(row=3, column=1) # Rows and columns configuration paramFrame.grid_columnconfigure(0, weight=1) paramFrame.grid_columnconfigure(1, weight=2) paramFrame.grid_columnconfigure(2, weight=1) paramFrame.grid_rowconfigure(0, weight=1) paramFrame.grid_rowconfigure(2, weight=2) paramFrame.grid_rowconfigure(4, weight=2)
def create_buttons(self, parent, create_sliders): self.jso = Button(parent, text="Import from .json", command=self.import_json) self.jso.grid(row=0, column=0, sticky="w") self.sav = Button(parent, text="Import from .sav", command=self.import_sav) self.sav.grid(row=0, column=1, sticky="w") self.scales = [] # create sliders if create_sliders: self.jso.grid_configure(row=0, column=0) self.sav.grid_configure(row=1, column=0) resources = [ 'minerals', 'energy', 'physics', 'society', 'engineering' ] colors = ["red", "yellow", "blue", "green", "orange"] for i in range(len(resources)): var = DoubleVar() var.set(500) callback = lambda event, tag=i: self.weight_update(event, tag) b = Scale(parent, from_=1, to=1000, variable=var, length=135, orient='horizontal', troughcolor=colors[i], resolution=1, label=resources[i], showvalue=0) b.grid(row=2 + i, column=0, sticky="w") b.bind('<ButtonRelease-1>', self.redraw) # redraw when user release scale self.scales.append(var)
class App: def __init__(self): # создание основного окна Tkinter self.window = Tk() self.window.title("Треугольники") self.window.geometry('520x520') self.window.minsize(520, 520) self.window.maxsize(520, 520) self.press_x, self.press_y = 0, 0 self.release_x, self.release_y = 0, 0 # флаги нажатия/отжатия кнопки self.pressed = False # размещение элементов интерфейса # основной элемент - Canvas self.canvas_x = 470 self.canvas_y = 270 self.c = Canvas(self.window, width=self.canvas_x, height=self.canvas_y, bg='black') self.c.pack(side=TOP, padx=10, pady=(10, 10)) # элементы управления: настройки, отображение параметров, очистка/выход setup = Frame(self.window, width=470) setup_left = Frame(setup, width=270) setup_right = Frame(setup, width=200) self.setup_notebook = Notebook(setup_left) setup1 = Frame(setup_left, width=250, height=140) setup2 = Frame(setup_left, width=250, height=140) setup3 = Frame(setup_left, width=250, height=140) # элементы управления на вкладках # вкладка 1 Label(setup1, text='Длина стороны').pack(side=TOP, pady=(10, 0), padx=(10, 0), anchor=W) self.scal_b = Scale(setup1, orient=HORIZONTAL, length=200, from_=0, to=300, tickinterval=100, resolution=10) self.scal_b.pack(side=TOP) self.scal_b.set(100) self.scal_b.bind("<ButtonRelease-1>", self.draw_triangle) Label(setup1, text='Угол \u03b1').pack(side=TOP, pady=(10, 0), padx=(10, 0), anchor=W) self.scal_alpha = Scale(setup1, orient=HORIZONTAL, length=200, from_=0, to=180, tickinterval=30, resolution=15) self.scal_alpha.pack(side=TOP) self.scal_alpha.set(30) self.scal_alpha.bind("<ButtonRelease-1>", self.draw_triangle) # вкладка 2 Label(setup2, text='Угол \u03b1').pack(side=TOP, pady=(10, 0), padx=(10, 0), anchor=W) self.scal_alpha2 = Scale(setup2, orient=HORIZONTAL, length=200, from_=0, to=90, tickinterval=15, resolution=5) self.scal_alpha2.pack(side=TOP) self.scal_alpha2.set(60) self.scal_alpha2.bind("<ButtonRelease-1>", self.draw_triangle) Label(setup2, text='Угол \u03b2').pack(side=TOP, pady=(10, 0), padx=(10, 0), anchor=W) self.scal_beta = Scale(setup2, orient=HORIZONTAL, length=200, from_=0, to=90, tickinterval=15, resolution=5) self.scal_beta.pack(side=TOP) self.scal_beta.set(60) self.scal_beta.bind("<ButtonRelease-1>", self.draw_triangle) # вкладка 3 Label(setup3, text='Длина стороны 2').pack(side=TOP, pady=(10, 0), padx=(10, 0), anchor=W) self.scal_a = Scale(setup3, orient=HORIZONTAL, length=200, from_=0, to=300, tickinterval=100, resolution=10) self.scal_a.pack(side=TOP) self.scal_a.set(100) self.scal_a.bind("<ButtonRelease-1>", self.draw_triangle) Label(setup3, text='Длина стороны 3').pack(side=TOP, pady=(10, 0), padx=(10, 0), anchor=W) self.scal_b2 = Scale(setup3, orient=HORIZONTAL, length=200, from_=0, to=300, tickinterval=100, resolution=10) self.scal_b2.pack(side=TOP) self.scal_b2.set(100) self.scal_b2.bind("<ButtonRelease-1>", self.draw_triangle) setup1.pack() setup2.pack() setup3.pack() self.setup_notebook.add(setup1, text='Задача 1') self.setup_notebook.add(setup2, text='Задача 2') self.setup_notebook.add(setup3, text='Задача 3') self.setup_notebook.bind('<<NotebookTabChanged>>', self.draw_triangle) self.setup_notebook.pack(side=LEFT) columns = ('#1', '#2') self.params = Treeview(setup_right, show='headings', columns=columns, height=5) self.params.heading('#1', text='Параметр') self.params.heading('#2', text='Значение') self.params.column('#1', width=110, minwidth=50, stretch=NO, anchor=N) self.params.column('#2', width=110, minwidth=50, stretch=NO, anchor=N) self.params.pack(side=TOP, padx=(15, 0), pady=(15, 5)) butframe = Frame(setup_right) Button(butframe, text='Очистить', width=10, command=self.draw_base()).pack(side=LEFT, padx=(25, 5)) Button(butframe, text='Выход', width=10, command=lambda x=0: sys.exit(x)).pack(side=LEFT, padx=(0, 10)) butframe.pack(side=TOP, pady=(17, 5)) setup_left.pack(side=LEFT, padx=(0, 20)) setup_right.pack(side=LEFT) setup.pack(side=TOP, pady=(5, 10), padx=(5, 5)) self.window.bind('<Button-1>', self.press) self.window.bind('<ButtonRelease-1>', self.release) self.window.bind('<Motion>', self.motion) self.draw_base() self.window.mainloop() def motion(self, event): if self.pressed: if event.widget.master is not None: if event.widget.widgetName == 'canvas': self.draw_base() self.c.create_line( [self.press_x, self.press_y, event.x, event.y], dash=True, fill='yellow') def draw_base(self): self.c.delete("all") # базовые оси self.c.create_line([10, 250, 460, 250], arrow=LAST, fill='white') self.c.create_line([20, 260, 20, 10], arrow=LAST, fill='white') # метки for i in range(1, 5): self.c.create_line([100 * i + 20, 247, 100 * i + 20, 253], fill='white') for i in range(1, 3): self.c.create_line([17, 250 - 100 * i, 23, 250 - 100 * i], fill='white') # надписи # наименование осей self.c.create_text(457, 258, text='x', fill='white') self.c.create_text(30, 15, text='y', fill='white') # наименование меток for i in range(0, 5): self.c.create_text(100 * i + 25, 260, text=str(100 * i), fill='white') for i in range(1, 3): self.c.create_text(34, 250 - 100 * i, text=str(100 * i), fill='white') def press(self, event): """ Обработчик события "нажатие кнопки мыши" :param event: :return: """ if event.widget.master is not None: if event.widget.widgetName == 'canvas': self.draw_base() self.press_x, self.press_y = event.x, event.y self.pressed = True def release(self, event): if event.widget.master is not None: if event.widget.widgetName == 'canvas': self.release_x, self.release_y = event.x, event.y if (self.release_x in range(450)) & (self.release_y in range(250)): self.draw_triangle(None) self.pressed = False def check_coordinates(self, C): if (C[0] < 0) | (C[1] < 0): return False if (C[0] > self.canvas_x) | (C[1] > self.canvas_y): return False return True def draw_triangle(self, event): if (self.press_x > 0) & (self.press_y > 0) & (self.release_x > 0) & ( self.release_y > 0): self.draw_base() triangle = Math((self.press_x, self.press_y), (self.release_x, self.release_y), (20, 250)) task = self.setup_notebook.index(self.setup_notebook.select()) + 1 if task == 1: data_dict = { 'b': self.scal_b.get(), 'alpha': self.scal_alpha.get() } elif task == 2: data_dict = { 'alpha': self.scal_alpha2.get(), 'beta': self.scal_beta.get() } elif task == 3: data_dict = {'a': self.scal_a.get(), 'b': self.scal_b2.get()} else: return C1, C2, data_dict = triangle.get_c(task, data_dict) if self.check_coordinates(C1) & self.check_coordinates(C2): self.c.create_polygon([ self.press_x, self.press_y, self.release_x, self.release_y, C1[0], C1[1] ], fill='red') self.c.create_polygon([ self.press_x, self.press_y, self.release_x, self.release_y, C2[0], C2[1] ], fill='blue') self.update_treeview(data_dict) else: self.c.create_text(300, 100, text='Одна из точек вне области построения', fill='white') def update_treeview(self, data): """ запись параметров в элемент Treeview :return: None """ for x in self.params.get_children(): self.params.delete(x) for key in data.keys(): self.params.insert("", END, values=[key, data[key]])
class Gui: """ This class is built to let the user have a better interaction with game. inputs => root = Tk() => an object which inherits the traits of Tkinter class agent = an object which inherit the traits of mctsagent class. """ agent_type = {1: "UCT", 2: "RAVE", 3: "LAST-GOOD-REPLY", 4: "POOLRAVE", 5: "DECISIVE-MOVE", 6: "UCB1-TUNED"} AGENTS = {"UCT": UctMctsAgent, "RAVE": RaveMctsAgent, "LAST-GOOD-REPLY": LGRMctsAgent, "POOLRAVE": PoolRaveMctsAgent, "DECISIVE-MOVE": DecisiveMoveMctsAgent, "UCB1-TUNED": UCB1TunedMctsAgent} def __init__(self, root, agent_name='UCT'): self.root = root self.root.geometry('1366x690+0+0') self.agent_name = agent_name try: self.agent = self.AGENTS[agent_name]() except KeyError: print("Unknown agent defaulting to basic") self.agent_name = "uct" self.agent = self.AGENTS[agent_name]() self.game = GameState(8) self.agent.set_gamestate(self.game) self.time = 1 self.root.configure(bg='#363636') self.colors = {'white': '#ffffff', 'milk': '#e9e5e5', 'red': '#9c0101', 'orange': '#ee7600', 'yellow': '#f4da03', 'green': '#00ee76', 'cyan': '#02adfd', 'blue': '#0261fd', 'purple': '#9c02fd', 'gray1': '#958989', 'gray2': '#3e3e3e', 'black': '#000000'} global BG BG = self.colors['gray2'] self.last_move = None self.frame_board = Frame(self.root) # main frame for the play board self.canvas = Canvas(self.frame_board, bg=BG) self.scroll_y = ttk.Scrollbar(self.frame_board, orient=VERTICAL) self.scroll_x = ttk.Scrollbar(self.frame_board, orient=HORIZONTAL) # the notebook frame which holds the left panel frames self.notebook = ttk.Notebook(self.frame_board, width=350) self.panel_game = Frame(self.notebook, highlightbackground=self.colors['white']) self.developers = Frame(self.notebook, highlightbackground=self.colors['white']) # Registering variables for: self.game_size_value = IntVar() # size of the board self.game_time_value = IntVar() # time of CPU player self.game_turn_value = IntVar() # defines whose turn is it self.switch_agent_value = IntVar() # defines which agent to play against self.switch_agent_value.set(1) self.game_turn_value.set(1) self.turn = {1: 'white', 2: 'black'} self.game_size = Scale(self.panel_game) self.game_time = Scale(self.panel_game) self.game_turn = Scale(self.panel_game) self.generate = Button(self.panel_game) self.reset_board = Button(self.panel_game) self.switch_agent = Scale(self.panel_game) self.agent_show = Label(self.panel_game, font=('Calibri', 14, 'bold'), fg='white', justify=LEFT, bg=BG, text='Agent Policy: ' + self.agent_name + '\n') self.hex_board = [] # Holds the IDs of hexagons in the main board for implementing the click and play functions self.game_size_value.set(8) self.game_time_value.set(1) self.size = self.game_size_value.get() self.time = self.game_time_value.get() self.board = self.game.board self.board = int_(self.board).tolist() self.gameboard2hexagons(self.board) # building the game board self.logo = PhotoImage(file='image/hex.png') self.uut_logo = PhotoImage(file='image/uut_2.png') self.generate_black_edge() self.generate_white_edge() # Frame_content self.frame_board.configure(bg=BG, width=1366, height=760) self.frame_board.pack(fill=BOTH) self.notebook.add(self.panel_game, text=' Game ') self.notebook.add(self.developers, text=' Developers ') self.notebook.pack(side=LEFT, fill=Y) self.canvas.configure(width=980, bg=BG, cursor='hand2') self.canvas.pack(side=LEFT, fill=Y) self.canvas.configure(yscrollcommand=self.scroll_y.set) self.scroll_y.configure(command=self.canvas.yview) self.scroll_x.configure(command=self.canvas.xview) self.scroll_y.place(x=387, y=482) self.scroll_x.place(x=370, y=500) # Frame_left_panel """ the left panel notebook ----> Game """ self.panel_game.configure(bg=BG) Label(self.panel_game, text='Board size', font=('Calibri', 14, 'bold'), foreground='white', bg=BG, pady=10).pack(fill=X, side=TOP) # label ---> Board size self.game_size.configure(from_=3, to=20, tickinterval=1, bg=BG, fg='white', orient=HORIZONTAL, variable=self.game_size_value) self.game_size.pack(side=TOP, fill=X) Label(self.panel_game, text='Time', font=('Calibri', 14, 'bold'), foreground='white', bg=BG, pady=10).pack(side=TOP, fill=X) # label ---> Time self.game_time.configure(from_=1, to=20, tickinterval=1, bg=BG, fg='white', orient=HORIZONTAL, variable=self.game_time_value) self.game_time.pack(side=TOP, fill=X) Label(self.panel_game, text='Player', font=('Calibri', 14, 'bold'), foreground='white', bg=BG, pady=10).pack(side=TOP, fill=X) # label ---> Turn self.game_turn.configure(from_=1, to=2, tickinterval=1, bg=BG, fg='white', orient=HORIZONTAL, variable=self.game_turn_value) self.game_turn.pack(side=TOP) Label(self.panel_game, text=' ', font=('Calibri', 14, 'bold'), foreground='white', bg=BG).pack(side=TOP, fill=X) # ################################## AGENT CONTROLS ############################# self.agent_show.pack(fill=X, side=TOP) self.switch_agent.configure(from_=1, to=len(self.agent_type), tickinterval=1, bg=BG, fg='white', orient=HORIZONTAL, variable=self.switch_agent_value, ) self.switch_agent.pack(side=TOP, fill=X) # ################################## MOVE LABELS ################################ self.move_label = Label(self.panel_game, font=('Calibri', 15, 'bold'), height=5, fg='white', justify=LEFT, bg=BG, text='PLAY : CLICK A CELL ON GAME BOARD \nMCTS BOT: CLICK GENERATE') self.move_label.pack(side=TOP, fill=X) self.reset_board.configure(text='Reset Board', pady=10, cursor='hand2', width=22, font=('Calibri', 12, 'bold')) self.reset_board.pack(side=LEFT) self.generate.configure(text='Generate', pady=10, cursor='hand2', width=22, font=('Calibri', 12, 'bold')) self.generate.pack(side=LEFT) """ the left panel notebook ---> Developers """ self.developers.configure(bg=BG) Label(self.developers, text='HEXPY', font=('Calibri', 18, 'bold'), foreground='white', bg=BG, pady=5).pack(side=TOP, fill=X) Label(self.developers, text='DEVELOPED BY:\n' + 'Masoud Masoumi Moghadam\n\n' + 'SUPERVISED BY:\n' + 'Dr.Pourmahmoud Aghababa\n' + 'Dr.Bagherzadeh\n\n' + 'SPECIAL THANKS TO:\n' + 'Nemat Rahmani\n', font=('Calibri', 16, 'bold'), justify=LEFT, foreground='white', bg=BG, pady=10).pack(side=TOP, fill=X) Label(self.developers, image=self.uut_logo, bg=BG).pack(side=TOP, fill=X) Label(self.developers, text='Summer 2016', font=('Calibri', 17, 'bold'), wraplength=350, justify=LEFT, foreground='white', bg=BG, pady=30).pack(side=TOP, fill=X) # Binding Actions """ Binding triggers for the actions defined in the class. """ self.canvas.bind('<1>', self.click2play) self.game_size.bind('<ButtonRelease>', self.set_size) self.game_time.bind('<ButtonRelease>', self.set_time) self.generate.bind('<ButtonRelease>', self.click_to_bot_play) self.reset_board.bind('<ButtonRelease>', self.reset) self.switch_agent.bind('<ButtonRelease>', self.set_agent) @staticmethod def top_left_hexagon(): """ Returns the points which the first hexagon has to be created based on. """ return [[85, 50], [105, 65], [105, 90], [85, 105], [65, 90], [65, 65]] def hexagon(self, points, color): """ Creates a hexagon by getting a list of points and their assigned colors according to the game board """ if color is 0: hx = self.canvas.create_polygon(points[0], points[1], points[2], points[3], points[4], points[5], fill=self.colors['gray1'], outline='black', width=2, activefill='cyan') elif color is 1: hx = self.canvas.create_polygon(points[0], points[1], points[2], points[3], points[4], points[5], fill=self.colors['yellow'], outline='black', width=2, activefill='cyan') elif color is 2: hx = self.canvas.create_polygon(points[0], points[1], points[2], points[3], points[4], points[5], fill=self.colors['red'], outline='black', width=2, activefill='cyan') elif color is 3: hx = self.canvas.create_polygon(points[0], points[1], points[2], points[3], points[4], points[5], fill=self.colors['black'], outline='black', width=2) else: hx = self.canvas.create_polygon(points[0], points[1], points[2], points[3], points[4], points[5], fill=self.colors['white'], outline='black', width=2) return hx def generate_row(self, points, colors): """ By getting a list of points as the starting point of each row and a list of colors as the dedicated color for each item in row, it generates a row of hexagons by calling hexagon functions multiple times. """ x_offset = 40 row = [] temp_array = [] for i in range(len(colors)): for point in points: temp_points_x = point[0] + x_offset * i temp_points_y = point[1] temp_array.append([temp_points_x, temp_points_y]) if colors[i] is 0: hx = self.hexagon(temp_array, 0) elif colors[i] is 1: hx = self.hexagon(temp_array, 4) else: hx = self.hexagon(temp_array, 3) row.append(hx) temp_array = [] return row def gameboard2hexagons(self, array): """ Simply gets the game_board and generates the hexagons by their dedicated colors. """ initial_offset = 20 y_offset = 40 temp = [] for i in range(len(array)): points = self.top_left_hexagon() for point in points: point[0] += initial_offset * i point[1] += y_offset * i temp.append([point[0], point[1]]) row = self.generate_row(temp, self.board[i]) temp.clear() self.hex_board.append(row) def generate_white_edge(self): """ Generates the white zones in the left and right of the board. """ init_points = self.top_left_hexagon() for pt in init_points: pt[0] -= 40 for pt in init_points: pt[0] -= 20 pt[1] -= 40 label_x, label_y = 0, 0 init_offset = 20 y_offset = 40 temp_list = [] for i in range(len(self.board)): for pt in range(len(init_points)): init_points[pt][0] += init_offset init_points[pt][1] += y_offset label_x += init_points[pt][0] label_y += init_points[pt][1] label_x /= 6 label_y /= 6 self.hexagon(init_points, 4) self.canvas.create_text(label_x, label_y, fill=self.colors['black'], font="Times 20 bold", text=chr(ord('A') + i)) label_x, label_y = 0, 0 for j in init_points: temp_list.append([j[0] + (len(self.board) + 1) * 40, j[1]]) self.hexagon(temp_list, 4) temp_list.clear() def generate_black_edge(self): """ Generates the black zones in the top and bottom of the board. """ init_points = self.top_left_hexagon() label_x, label_y = 0, 0 temp_list = [] for pt in init_points: pt[0] -= 60 pt[1] -= 40 for t in range(len(init_points)): init_points[t][0] += 40 label_x += init_points[t][0] label_y += init_points[t][1] label_x /= 6 label_y /= 6 for i in range(len(self.board)): self.hexagon(init_points, 3) self.canvas.create_text(label_x, label_y, fill=self.colors['white'], font="Times 20 bold", text=i + 1) label_x, label_y = 0, 0 for pt in init_points: temp_list.append([pt[0] + (len(self.board) + 1) * 20, pt[1] + (len(self.board) + 1) * 40]) self.hexagon(temp_list, 3) temp_list.clear() for j in range(len(init_points)): init_points[j][0] += 40 label_x += init_points[j][0] label_y += init_points[j][1] label_x /= 6 label_y /= 6 def click2play(self, event): """ Whenever any of the hexagons in the board is clicked, depending on the player turns, it changes the color of hexagon to the player assigned color. """ if self.winner() == 'none': x = self.canvas.canvasx(event.x) y = self.canvas.canvasy(event.y) idd = self.canvas.find_overlapping(x, y, x, y) idd = list(idd) if len(idd) is not 0: clicked_cell = idd[0] if any([clicked_cell in x for x in self.hex_board]): coordinated_cell = clicked_cell - self.hex_board[0][0] col = (coordinated_cell % self.size) turn = self.turn[self.game_turn_value.get()] if coordinated_cell % self.size == 0: row = int(coordinated_cell / self.size) else: row = int(coordinated_cell / self.size) cell = str(chr(65 + row)) + str(col + 1) self.move_label.configure(text=str(turn) + ' played ' + cell, justify=LEFT, height=5) if self.board[row][col] == 0: self.board[row][col] = self.game_turn_value.get() if self.game_turn_value.get() == 1: self.game_turn_value.set(2) else: self.game_turn_value.set(1) self.refresh() y = row x = col if turn[0].lower() == 'w': self.last_move = (x, y) if self.game.turn() == GameMeta.PLAYERS["white"]: self.game.play((x, y)) self.agent.move((x, y)) if self.winner() != 'none': messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner()) return else: self.game.place_white((x, y)) self.agent.set_gamestate(self.game) if self.winner() != 'none': messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner()) return elif turn[0].lower() == 'b': self.last_move = (x, y) if self.game.turn() == GameMeta.PLAYERS["black"]: self.game.play((x, y)) self.agent.move((x, y)) if self.winner() != 'none': messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner()) return else: self.game.place_black((x, y)) self.agent.set_gamestate(self.game) if self.winner() != 'none': messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner()) return else: messagebox.showinfo(" GAME OVER ", " The game is already over! Winner is %s" % self.winner()) def set_size(self, event): """ It changes the board size and reset the whole game. """ self.canvas.delete('all') self.size = self.game_size_value.get() self.game = GameState(self.size) self.agent.set_gamestate(self.game) self.board = self.game.board self.board = int_(self.board).tolist() self.last_move = None self.move_label.config(text='PLAY : CLICK A CELL ON GAME BOARD \nMCTS BOT: CLICK GENERATE', justify='left', height=5) self.refresh() def set_time(self, event) -> None: """ It changes the time for CPU player to think and generate a move. """ self.time = self.game_time_value.get() print('The CPU time = ', self.time, ' seconds') def set_agent(self, event) -> None: """ It changes the time for CPU player to think and generate a move. """ agent_num = self.switch_agent_value.get() self.agent_name = self.agent_type[agent_num] self.agent = self.AGENTS[self.agent_name](self.game) self.agent_show.config(font=('Calibri', 14, 'bold'), justify=LEFT, text='Agent Policy: ' + self.agent_name + '\n') def winner(self) -> str: """ Return the winner of the current game (black or white), none if undecided. """ if self.game.winner == GameMeta.PLAYERS["white"]: return "white" elif self.game.winner == GameMeta.PLAYERS["black"]: return "black" else: return "none" def click_to_bot_play(self, event): """ By pushing the generate button, It produces an appropriate move by using monte carlo tree search algorithm for the player which turn is his/hers! . """ if self.winner() == 'none': self.agent.search(self.time) num_rollouts, node_count, run_time = self.agent.statistics() move = self.agent.best_move() # the move is tuple like (3, 1) self.game.play(move) self.agent.move(move) row, col = move # Relating the 'move' tuple with index of self.board self.board[col][row] = self.game_turn_value.get() if self.game_turn_value.get() == 1: # change the turn of players self.game_turn_value.set(2) else: self.game_turn_value.set(1) self.refresh() player = self.turn[self.game_turn_value.get()] cell = chr(ord('A') + move[1]) + str(move[0] + 1) self.move_label.config(font=('Calibri', 15, 'bold'), justify='left', text=str(num_rollouts) + ' Game Simulations ' + '\n' + 'In ' + str(run_time) + ' seconds ' + '\n' + 'Node Count : ' + str(node_count) + '\n' + player + ' played at ' + cell, height=5) print('move = ', cell) if self.winner() != 'none': messagebox.showinfo(" GAME OVER", " Oops!\n You lost! \n Winner is %s" % self.winner()) else: messagebox.showinfo(" GAME OVER", " The game is already over! Winner is %s" % self.winner()) def refresh(self): """ Delete the whole world and recreate it again """ self.canvas.delete('all') self.hex_board.clear() self.gameboard2hexagons(self.board) self.generate_black_edge() self.generate_white_edge() def reset(self, event): """ By clicking on the Reset button game board would be cleared for a new game """ self.game = GameState(self.game.size) self.agent.set_gamestate(self.game) self.set_size(event) self.last_move = None self.game_turn_value.set(1) self.move_label.config(text='PLAY : CLICK A CELL ON GAME BOARD \nMCTS BOT: CLICK GENERATE', justify='left', height=5)
class ControlAppGUI: def __init__(self, master): self.master = master # GUI layout setup self.menu = Menu(self.master) self.master.config(menu=self.menu) master.grid_rowconfigure(0, weight=1) master.grid_columnconfigure(0, weight=1) filemenu = Menu(self.menu) self.menu.add_cascade(label="File", menu=filemenu) filemenu.add_command(label="New", command=self.NewFile) openmenu = Menu(self.menu) openmenu.add_command(label="Gcode", command=self.OpenGcodeFile) openmenu.add_command(label="CSV", command=self.OpenCsvFile) savemenu = Menu(self.menu) savemenu.add_command(label="Gcode", command=self.SaveGcodeFile) savemenu.add_command(label="CSV", command=self.SaveCsvFile) filemenu.add_cascade(label='Open...', menu=openmenu, underline=0) filemenu.add_cascade(label="Save...", menu=savemenu, underline=0) #filemenu.add_command(label="Reload current file", command=None) filemenu.add_command(label="Set color", command=self.AskColor) filemenu.add_separator() def updatePortList(): ports = serial.serial_ports() self.portCombo['values'] = ports if len(ports) > 0: self.portCombo.current(0) filemenu.add_command(label="Refresh port list", command=updatePortList) filemenu.add_command(label="Exit", command=self.Quit) editmenu = Menu(self.menu) self.menu.add_cascade(label="Edit", menu=editmenu) editmenu.add_command(label="Settings", command=self.Settings) helpmenu = Menu(self.menu) self.menu.add_cascade(label="Help", menu=helpmenu) helpmenu.add_command(label="About...", command=self.About) master.title("Embroiderino frontend") self.controls = ttk.Notebook(master) tab1 = Frame(self.controls) tab2 = Frame(self.controls) self.controls.add(tab1, text="Machine control") self.controls.add(tab2, text="Path manipulation") self.controls.grid(row=0, column=1, sticky=N) self.controls.grid_rowconfigure(0, weight=1) self.controls.grid_columnconfigure(0, weight=1) # MACHINE TAB ports = serial.serial_ports() self.portCombo = ttk.Combobox(tab1, values=ports) if len(ports) > 0: self.portCombo.current(0) self.portCombo.grid(row=1, column=0) self.baudCombo = ttk.Combobox(tab1, state='readonly', values=("115200", "9600"), width=10) self.baudCombo.current(0) self.baudCombo.grid(row=1, column=1) self.connectButton = Button(tab1, text="Connect", command=self.ToggleConnect, width=10) self.connectButton.grid(row=1, column=2) self.startButton = Button(tab1, text="Start job", command=self.ToggleStart, state=DISABLED) self.startButton.grid(row=2, column=1) self.homeButton = Button(tab1, text="Home machine", command=lambda: serial.queue_command("G28\n"), state=DISABLED) self.homeButton.grid(row=2, column=0) testNavigation = Frame(tab1) leftButton = Button( testNavigation, text="<", command=lambda: serial.queue_command("G91\nG0 X-2\nG90\n"), state=DISABLED) leftButton.grid(row=1, column=0) rightButton = Button( testNavigation, text=">", command=lambda: serial.queue_command("G91\nG0 X2\nG90\n"), state=DISABLED) rightButton.grid(row=1, column=2) upButton = Button( testNavigation, text="/\\", command=lambda: serial.queue_command("G91\nG0 Y2\nG90\n"), state=DISABLED) upButton.grid(row=0, column=1) downButton = Button( testNavigation, text="\\/", command=lambda: serial.queue_command("G91\nG0 Y-2\nG90\n"), state=DISABLED) downButton.grid(row=2, column=1) testNavigation.grid(row=3, column=0) self.navigationButtons = [ leftButton, rightButton, upButton, downButton ] self.testButton = Button(tab1, text="Test border path", command=self.TestBorder, state=DISABLED) self.testButton.grid(row=3, column=1) self.gotoButton = Button(tab1, text="Go to", command=self.GoTo, state=DISABLED, relief=RAISED) self.gotoButton.grid(row=3, column=2) self.stopButton = Button(tab1, text="STOP", command=self.StopAll, state=DISABLED) self.stopButton.grid(row=4, column=0) self.pauseOnToolChange = IntVar() self.pauseOnTrim = IntVar() self.toolChangeCheck = Checkbutton(tab1, variable=self.pauseOnToolChange, onvalue=1, offvalue=0, text="Pause on tool change") self.toolChangeCheck.grid(row=4, column=1) self.toolChangeCheck.select() self.trimCheck = Checkbutton(tab1, variable=self.pauseOnTrim, onvalue=1, offvalue=0, text="Pause on trim") self.trimCheck.grid(row=4, column=2) self.trimCheck.select() progressFrame = Frame(tab1) Label(progressFrame, text="Tool changes: ", bd=1).grid(row=0, column=0, pady=(10, 1)) self.toolChangesLabel = Label(progressFrame, text="0/0", bd=1, relief=SUNKEN) self.toolChangesLabel.grid(row=1, column=0) Label(progressFrame, text="Tool points: ", bd=1).grid(row=0, column=2, pady=(10, 1)) self.toolPointsLabel = Label(progressFrame, text="0/0", bd=1, relief=SUNKEN) self.toolPointsLabel.grid(row=1, column=2) Label(progressFrame, text="Estimated endtime: ", bd=1).grid(row=0, column=4, pady=(10, 1)) self.timeLabel = Label(progressFrame, text="0/0", bd=1, relief=SUNKEN) self.timeLabel.grid(row=1, column=4) progressFrame.grid(row=5, column=0, columnspan=3) colorsFrame = Frame(tab1, bd=1) colorsFrame.grid(row=6, column=0, columnspan=3, pady=(10, 1)) Label(colorsFrame, text="Current color: ", bd=1).pack(side=LEFT) self.currentColorIndicator = Label(colorsFrame, text=" ", relief=RAISED, bd=1) self.currentColorIndicator.pack(side=LEFT, padx=(1, 40)) Label(colorsFrame, text="Next color: ", bd=1).pack(side=LEFT, padx=2) self.nextColorIndicator = Label(colorsFrame, text=" ", relief=RAISED, bd=1) self.nextColorIndicator.pack(side=LEFT) Label(tab1, text="SPM speed limit: ", bd=1).grid(row=7, column=0) self.speedSlider = Scale(tab1, from_=80, to=800, command=None, orient=HORIZONTAL, length=200) self.speedSlider.set(400) self.speedSlider.bind( "<ButtonRelease-1>", lambda _: serial.queue_command( "M222 S%d\n" % self.speedSlider.get(), priority=-1)) self.speedSlider.grid(row=7, column=1, columnspan=2) # PATH TAB tab2.grid_columnconfigure(0, weight=1) Label(tab2, text="Display progress: ", bd=1).grid(row=0) self.slider = Scale(tab2, from_=0, to=0, command=self.UpdatePath, orient=HORIZONTAL, length=300) self.slider.grid(row=1) toolbar = Frame(tab2, bd=1, relief=RAISED) toolbar.grid(row=2) self.panButton = Button(toolbar, relief=RAISED, command=self.TogglePan, text="Move path") self.panButton.pack(side=LEFT, padx=2, pady=2) self.rotateButton = Button(toolbar, relief=RAISED, command=self.ToggleRotate, text="Rotate path") self.rotateButton.pack(side=LEFT, padx=2, pady=2) self.mirrorButton = Button(toolbar, relief=RAISED, command=self.ToggleMirror, text="Mirror path") self.mirrorButton.pack(side=LEFT, padx=2, pady=2) self.scaleButton = Button(toolbar, relief=RAISED, command=self.ToggleScale, text="Scale path") self.scaleButton.pack(side=LEFT, padx=2, pady=2) # CANVAS canvasFrame = Frame(master) canvasFrame.grid(row=0, column=0, sticky='NWES') self.canvas = ResizingCanvas(canvasFrame, width=400, height=400, bg="white", highlightthickness=0) self.canvas.bind("<B1-Motion>", self.CanvasDrag) self.canvas.bind("<Button-1>", self.CanvasClick) self.canvas.bind("<ButtonRelease-1>", self.CanvasRelease) self.canvas.pack(expand=YES, anchor=N + W) #STATUS BAR self.status = Label(master, text="Not connected", bd=1, relief=SUNKEN, anchor=W) self.status.grid(row=2, columnspan=2, sticky='WE') # PROGRAM VARIABLES self.SETTINGSFNAME = "settings.pickle" self.commands = [] self.transform = (0, 0) self.isConnected = False self.isJobRunning = False self.isJobPaused = False self.lastSendCommandIndex = -1 self.lastMove = None self.currentColor = 'black' self.currentToolChange = 0 self.toolChangesTotal = 0 self.currentToolPoint = 0 self.toolPointsTotal = 0 self.distancesList = [] self.distanceTraveled = 0 self.positionResponseRegex = re.compile( "X:(\-?\d+\.\d+),Y:(\-?\d+\.\d+)") self.machineSetups = {} self.currentSetupName = None self.workAreaSize = [100, 100] self.workAreaOrigin = [0, 0] # LOAD SOME SETTIGS self.loadSettings() self.canvas.setArea(self.workAreaSize[0], self.workAreaSize[1]) self.canvas.setOrigin(self.workAreaOrigin[0], self.workAreaOrigin[1]) # UI LOGIC def Quit(self): if messagebox.askyesno('Confirm', 'Really quit?'): self.master.quit() return True return False def AskColor(self): color = colorchooser.askcolor(title="Colour Chooser") def NewFile(self): if self.isJobRunning: return self.toolChangesTotal = 0 self.toolPointsTotal = 0 self.distancesList = [] self.lastSendCommandIndex = -1 self.lastMove = None self.commands = [] self.canvas.clear() self.slider.config(to=0) def OpenGcodeFile(self): if self.isJobRunning: return with filedialog.askopenfile(filetypes=(("Machine G-code", "*.gcode"), )) as f: self.commands = load_gcode_file(f) self.FinishLoading() def SaveGcodeFile(self): if not self.commands: return with filedialog.asksaveasfile(filetypes=(("Machine G-code", "*.gcode"), ), defaultextension='.gcode') as f: save_gcode_file(f, self.commands) def OpenCsvFile(self): if self.isJobRunning: return with filedialog.askopenfile(filetypes=(("Comma separated values", "*.csv"), )) as f: self.commands = load_csv_file(f) self.FinishLoading() def SaveCsvFile(self): pass def FinishLoading(self): points_count = len(self.commands) # file loaded if points_count > 2: self.testButton.config(state=NORMAL) self.startButton.config(state=NORMAL) # prepare color indicators self.currentColorIndicator.configure(background=self.currentColor) self.currentColorIndicator.configure(background=None) # center loaded path rectangle = toolpath_border_points(self.commands) rwidth = rectangle[2][0] - rectangle[0][0] rheight = rectangle[2][1] - rectangle[0][1] center = (rectangle[2][0] - (rwidth) / 2, rectangle[2][1] - (rheight) / 2) transform = (self.workAreaSize[0] / 2 - center[0] + self.workAreaOrigin[0], self.workAreaSize[1] / 2 - center[1] + self.workAreaOrigin[1]) self.commands = translate_toolpath(self.commands, transform) # check if design is bigger than available workarea if (rwidth > self.workAreaSize[0] or rheight > self.workAreaSize[1]): messagebox.showinfo( 'Size Warning!', "Looks like this design is bigger than available work area." ) self.slider.config(to=points_count) self.slider.set(points_count) self.toolPointsTotal, self.toolChangesTotal, self.distancesList = toolpath_info( self.commands) self.toolPointsLabel.config( text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal)) self.toolChangesLabel.config( text="%d/%d" % (self.currentToolChange, self.toolChangesTotal)) self.UpdateTimeEstLabel() self.canvas.draw_toolpath(self.commands) def About(self): #self.PausePopup() messagebox.showinfo( 'About this software', 'This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nWritten in 2018 by markol.' ) def Settings(self): tl = Toplevel(root) tl.title("Global settings") frame = Frame(tl) frame.grid() machineFrame = LabelFrame(frame, text="Machine hoop workarea (mm)", relief=RIDGE) machineFrame.grid() Label(machineFrame, text="width ").grid(row=0, column=0, sticky=N) workareaWidth = Entry(machineFrame, text="1") workareaWidth.grid(row=0, column=1) Label(machineFrame, text="height ").grid(row=2, column=0, sticky=N) workareaHeight = Entry(machineFrame, text="2") workareaHeight.grid(row=2, column=1) hoopFrame = LabelFrame(frame, text="Machine hoop origin (mm)", relief=RIDGE) hoopFrame.grid() Label(hoopFrame, text="X ").grid(row=0, column=0, sticky=N) workareaOriginX = Entry(hoopFrame, text="3") workareaOriginX.grid(row=0, column=1) Label(hoopFrame, text="Y ").grid(row=2, column=0, sticky=N) workareaOriginY = Entry(hoopFrame, text="4") workareaOriginY.grid(row=2, column=1) Label(hoopFrame, text="Setup name ").grid(row=3, column=0, sticky=N) setupName = Entry(hoopFrame, text="Setup1") setupName.grid(row=3, column=1) def setupSelected(event=None): if event: selectedSetupName = setupsCombo.get() else: selectedSetupName = self.currentSetupName workareaWidth.delete(0, END) workareaWidth.insert( 0, str(self.machineSetups[selectedSetupName]["workAreaSize"][0])) workareaHeight.delete(0, END) workareaHeight.insert( 0, str(self.machineSetups[selectedSetupName]["workAreaSize"][1])) workareaOriginX.delete(0, END) workareaOriginX.insert( 0, str(self.machineSetups[selectedSetupName]["workAreaOrigin"] [0])) workareaOriginY.delete(0, END) workareaOriginY.insert( 0, str(self.machineSetups[selectedSetupName]["workAreaOrigin"] [1])) setupName.delete(0, END) setupName.insert(0, selectedSetupName) setupSelected() setupsCombo = ttk.Combobox(frame, values=list(self.machineSetups.keys()), state="readonly") setupsCombo.grid(row=2, column=0) setupsCombo.current(setupsCombo['values'].index(self.currentSetupName)) setupsCombo.bind("<<ComboboxSelected>>", setupSelected) def addSettings(): newSetupName = setupName.get() if newSetupName in self.machineSetups.keys(): if not messagebox.askyesno( "Machine setup exists", "Machine setup with this name exists. Overwrite?"): return newSetup = { "workAreaSize": (int(workareaWidth.get()), int(workareaHeight.get())), "workAreaOrigin": (int(workareaOriginX.get()), int(workareaOriginY.get())) } self.machineSetups[newSetupName] = newSetup setupsCombo['values'] = list(self.machineSetups.keys()) Button(frame, relief=RAISED, command=addSettings, text="Add setup").grid(row=2, column=1) def removeSetup(): self.machineSetups.pop(setupsCombo.get(), None) options = list(self.machineSetups.keys()) setupsCombo['values'] = options if len(options) > 0: self.currentSetupName = list(self.machineSetups.keys())[0] setupsCombo.current(0) setupSelected(1) Button(frame, relief=RAISED, command=removeSetup, text="Remove setup").grid(row=2, column=2) def saveSettings(): try: if len(setupsCombo.get()) > 0: self.workAreaSize = (int(workareaWidth.get()), int(workareaHeight.get())) self.workAreaOrigin = (int(workareaOriginX.get()), int(workareaOriginY.get())) self.currentSetupName = setupsCombo.get() except: messagebox.showerror( "Invalid numeric values", "Please provide correct workarea values!") return self.canvas.setArea(self.workAreaSize[0], self.workAreaSize[1]) self.canvas.setOrigin(self.workAreaOrigin[0], self.workAreaOrigin[1]) self.storeSettings() TmpDim = namedtuple('TmpDim', 'width height') tmp = TmpDim(self.canvas.width, self.canvas.height) self.canvas.on_resize(tmp) Button(frame, text="Save", command=saveSettings, width=10).grid(row=3, column=3) Button(frame, text="Close", command=lambda: tl.destroy(), width=10).grid(row=3, column=2) def loadSettings(self): try: with open(self.SETTINGSFNAME, "rb") as f: data = pickle.load(f) self.machineSetups = data["machineSetups"] self.currentSetupName = data["currentSetupName"] self.workAreaSize = self.machineSetups[ self.currentSetupName]["workAreaSize"] self.workAreaOrigin = self.machineSetups[ self.currentSetupName]["workAreaOrigin"] except Exception as e: print("Unable to restore program settings:", str(e)) def storeSettings(self): with open(self.SETTINGSFNAME, "wb") as f: try: data = { "machineSetups": self.machineSetups, "currentSetupName": self.currentSetupName } pickle.dump(data, f) except Exception as e: print("Error while saving settings:", str(e)) def ToggleConnect(self): if self.isConnected: serial.close_serial() self.connectButton.config(text="Connect") self.status.config(text="Not connected") self.homeButton.config(state=DISABLED) self.stopButton.config(state=DISABLED) self.gotoButton.config(state=DISABLED) self.SetNavButtonsState(False) self.isConnected = False else: if serial.open_serial(self.portCombo.get(), self.baudCombo.get()): self.connectButton.config(text="Disconnect") self.status.config(text="Connected") self.homeButton.config(state=NORMAL) self.stopButton.config(state=NORMAL) self.gotoButton.config(state=NORMAL) self.SetNavButtonsState(True) self.isConnected = True self.GetPositionTimerTaks() def TestBorder(self): rectangle = toolpath_border_points(self.commands) for point in rectangle: serial.queue_command("G0 X%f Y%f F5000\n" % point) def ToggleStart(self): if self.isJobPaused: serial.queue.clear() self.startButton.config(text="Resume job") self.status.config(text="Job paused") else: self.startButton.config(text="Pause job") self.status.config(text="Job in progress") startInstructionIndex = self.lastSendCommandIndex + 1 # job launch if not self.isJobRunning: self.canvas.clear() startInstructionIndex = 0 self.start = time.time() serial.queue_command("G0 F15000\n") self.isJobRunning = True self.QueueCommandsBlock(startInstructionIndex) self.isJobPaused = not self.isJobPaused def QueueCommandsBlock(self, startInstructionIndex): commandsCount = len(self.commands) def progressCallback(instruction_index): ''' after every move G0 or G1 or G28 command being sent, this callback is executed ''' point = self.commands[instruction_index] if self.lastMove: coord = (self.lastMove[1], self.lastMove[2], point[1], point[2]) color = self.currentColor # set color for jump move if "G0" == point[0] or "G28" == point[0]: color = "snow2" else: self.currentToolPoint += 1 self.toolPointsLabel.config( text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal)) # calculate distance for material usage self.distanceTraveled += math.hypot( coord[0] - coord[2], coord[1] - coord[3]) # draw new line on canvas line = self.canvas.create_line(self.canvas.calc_coords(coord), fill=color) self.canvas.lift(self.canvas.pointer, line) self.UpdateTimeEstLabel() # store next start point and instruction index self.lastSendCommandIndex = instruction_index self.lastMove = point # update status bar if self.currentToolPoint % 10 == 0: progress = instruction_index / commandsCount * 100 self.status.config(text="Job in progress %.1f%%" % progress) def progressPauseCallback(instruction_index, trim=False): ''' this callback pauses the job ''' point = self.commands[instruction_index] self.lastSendCommandIndex = instruction_index # pause on color change if not trim: self.currentColor = _from_rgb((point[1], point[2], point[3])) self.currentToolChange += 1 self.currentColorIndicator.configure( background=self.currentColor) self.toolChangesLabel.config( text="%d/%d" % (self.currentToolChange, self.toolChangesTotal)) # pause enabled or not if self.pauseOnToolChange.get() == 1: self.ToggleStart() self.PausePopup(self.currentColor) else: self.QueueCommandsBlock(self.lastSendCommandIndex + 1) # pause on trim else: # pause enabled or not if self.pauseOnTrim.get() == 1: self.ToggleStart() self.PausePopup(self.currentColor, trim) else: self.QueueCommandsBlock(self.lastSendCommandIndex + 1) # all the commands until next tool change command, are queued at once # unsupported commands are ignored for i in range(startInstructionIndex, commandsCount): point = self.commands[i] # pause on color change if "M6" == point[0]: serial.queue_command( "M6\n", lambda _, index=i: progressPauseCallback(index)) self.nextColorIndicator.configure( background=_from_rgb((point[1], point[2], point[3]))) break # pause on trim elif "G12" == point[0]: # if next command is a color change, there is no need to pause now if i < commandsCount + 1 and self.commands[ i + 1][0] == "M6" and self.pauseOnToolChange.get() == 1: serial.queue_command("G12\n") else: serial.queue_command( "G12\n", lambda _, index=i: progressPauseCallback(index, trim=True)) break elif "G1" == point[0] or "G0" == point[0] or "G28" == point[0]: serial.queue_command( "%s X%f Y%f\n" % (point[0], point[1], point[2]), lambda _, index=i: progressCallback(index)) # queue job finish callback if i + 1 >= commandsCount: serial.queue_command("M114\n", self.JobFinished) def SetNavButtonsState(self, enabled=False): newState = NORMAL if enabled else DISABLED for b in self.navigationButtons: b.config(state=newState) def TogglePan(self): self.rotateButton.config(relief=RAISED) self.scaleButton.config(relief=RAISED) if self.isJobRunning: return if self.panButton.config('relief')[-1] == SUNKEN: self.panButton.config(relief=RAISED) else: self.panButton.config(relief=SUNKEN) def ToggleRotate(self): self.panButton.config(relief=RAISED) self.scaleButton.config(relief=RAISED) if self.isJobRunning: return if self.rotateButton.config('relief')[-1] == SUNKEN: self.rotateButton.config(relief=RAISED) else: self.rotateButton.config(relief=SUNKEN) def ToggleMirror(self): self.panButton.config(relief=RAISED) self.rotateButton.config(relief=RAISED) self.scaleButton.config(relief=RAISED) if self.isJobRunning: return self.commands = reflect_toolpath( self.commands, self.workAreaSize[0] / 2 + self.workAreaOrigin[0]) self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())]) def ToggleScale(self): self.panButton.config(relief=RAISED) self.rotateButton.config(relief=RAISED) self.mirrorButton.config(relief=RAISED) if self.isJobRunning: return if self.scaleButton.config('relief')[-1] == SUNKEN: self.scaleButton.config(relief=RAISED) else: self.scaleButton.config(relief=SUNKEN) def GoTo(self): if self.isJobRunning: return if self.gotoButton.config('relief')[-1] == SUNKEN: self.gotoButton.config(relief=RAISED) else: self.gotoButton.config(relief=SUNKEN) def StopAll(self): serial.queue.clear() self.JobFinished(False) self.status.config(text="Job stopped on user demand") def JobFinished(self, messagePopup=True): self.isJobRunning = False self.isJobPaused = False self.lastSendCommandIndex = -1 self.lastMove = None self.distanceTraveled = 0 self.currentToolChange = 0 self.currentToolPoint = 0 self.currentColor = 'black' self.toolPointsLabel.config( text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal)) self.toolChangesLabel.config( text="%d/%d" % (self.currentToolChange, self.toolChangesTotal)) self.UpdateTimeEstLabel() self.startButton.config(text="Start job") self.status.config(text="Job finished") timeTaken = time.time() - self.start # non blocking popup messagebox if messagePopup: tl = Toplevel(root) # this pop-up is always on top and other windows are deactivated tl.attributes('-topmost', 'true') tl.title("Job finished") tl.grab_set() frame = Frame(tl) frame.grid() Label(frame, text='Current job is finished and took %s.' % time.strftime("%H hours, %M minutes, %S seconds", time.gmtime(timeTaken))).grid(row=0, column=0, sticky=N) Button(frame, text="OK", command=lambda: tl.destroy(), width=10).grid(row=1, column=0) def CanvasClick(self, event): if self.isJobRunning: return self.dragStart = [event.x, event.y] #self.transform = math.atan2(event.x, event.y) self.transform = 0 # go to if self.gotoButton.config('relief')[-1] == SUNKEN: point = self.canvas.canvas_point_to_machine(self.dragStart) serial.queue_command("G0 X%f Y%f\n" % point) #print("Clicked at: ", self.dragStart) def CanvasRelease(self, event): if self.isJobRunning: return print("Applied transform", self.transform) def CanvasDrag(self, event): if self.isJobRunning: return vect = (self.dragStart[0] - event.x, self.dragStart[1] - event.y) # move event if self.panButton.config('relief')[-1] == SUNKEN: self.transform = self.canvas.canvas_vector_to_machine(vect) self.commands = translate_toolpath(self.commands, self.transform) self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())]) self.dragStart[0] = event.x self.dragStart[1] = event.y # rotate event if self.rotateButton.config('relief')[-1] == SUNKEN: angle = math.atan2(vect[0], vect[1]) # atan2(y, x) or atan2(sin, cos) self.commands = rotate_toolpath( self.commands, (self.workAreaSize[0] / 2 + self.workAreaOrigin[0], self.workAreaSize[1] / 2 + self.workAreaOrigin[1]), -(self.transform - angle)) self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())]) self.transform = angle # scale event if self.scaleButton.config('relief')[-1] == SUNKEN: factor = math.sqrt((vect[0])**2 + (vect[1])**2) / 500 f = factor - self.transform if vect[0] < 0: f = -f self.commands = scale_toolpath(self.commands, f) self.canvas.draw_toolpath(self.commands[0:int(self.slider.get())]) self.transform = factor def UpdatePath(self, val): if self.isJobRunning: return self.canvas.draw_toolpath(self.commands[0:int(val)]) def UpdateTimeEstLabel(self): # avg milimeters per second factor factor = 11.0 time_to_toolchange = (self.distancesList[self.currentToolChange] - self.distanceTraveled) / factor time_total = (self.distancesList[-1] - self.distanceTraveled) / factor self.timeLabel.config(text="%d m %d s/%d m %d s" % (time_to_toolchange / 60, time_to_toolchange % 60, time_total / 60, time_total % 60)) def GetPositionTimerTaks(self): if self.isConnected: def TimerCallback(response): response = self.positionResponseRegex.search(response) if response: pos = (float(response.group(1)), float(response.group(2))) self.canvas.move_pointer(pos) serial.queue_command("M114\n", TimerCallback, priority=-1) self.master.after(2000, self.GetPositionTimerTaks) def CleanUp(self): serial.close_serial() def PausePopup(self, newColor="black", trim=False): tl = Toplevel(root) tl.attributes('-topmost', 'true') tl.grab_set() tl.title("Tool change") msg = "change the tool for a next color" if trim: tl.title("Thread trim") msg = "cut the thread" frame = Frame(tl) frame.grid() canvas = Canvas(frame, width=64, height=64) canvas.grid(row=2, column=0) canvas.create_rectangle(0, 0, 65, 65, fill=newColor) msgbody = Label( frame, text= "There is the moment to %s. Resume the current job after change." % msg) msgbody.grid(row=1, column=0, sticky=N) okbttn = Button(frame, text="OK", command=lambda: tl.destroy(), width=10) okbttn.grid(row=2, column=2)
class ipGUI: def __init__(self, master): self.master = master self.master.minsize(width=800, height=600) menu = Menu(self.master) master.config(menu=menu) # ***** Main Menu ***** # *** file menu *** fileMenu = Menu(menu) menu.add_cascade(label='File', menu=fileMenu) fileMenu.add_command(label="Open", command=self.openImage) fileMenu.add_command(label="Load Blur Kernel", command=self.loadKernel) fileMenu.add_command(label="Save", command=self.saveImage) fileMenu.add_command(label="Exit", command=master.destroy) # *** edit menu *** editMenu = Menu(menu) menu.add_cascade(label='Space', menu=editMenu) editMenu.add_command(label="Histogram Equalization", command=self.histWrap) editMenu.add_command(label="Gamma Correction", command=self.gammaCorWrap) editMenu.add_command(label="Log Transform", command=self.logTranWrap) editMenu.add_command(label="Sharpen", command=self.sharpWrap) editMenu.add_command(label="Cartoonify", command=self.cartoonifyWrap) # *** blur menu *** blurMenu = Menu(editMenu) editMenu.add_cascade(label='Blur', menu=blurMenu) blurMenu.add_command(label="Box", command=self.boxBlurWrap) blurMenu.add_command(label="Gaussian", command=self.gaussianBlurWrap) blurMenu.add_command(label="Median", command=self.medianBlurWrap) # *** frequency filtering *** freqMenu = Menu(menu) menu.add_cascade(label='Frequency', menu=freqMenu) freqMenu.add_command(label="DFT", command=self.dftWrap) freqMenu.add_command(label="Load Mask", command=self.freqMaskWrap) # *** Mask Menu *** maskMenu = Menu(freqMenu) freqMenu.add_cascade(label='Create Mask', menu=maskMenu) maskMenu.add_command(label='Low Pass', command=self.lpmWrap) maskMenu.add_command(label='High Pass', command=self.hpmWrap) maskMenu.add_command(label='Band Pass', command=self.bppmWrap) maskMenu.add_command(label='Band Stop', command=self.bspmWrap) # *** frequency filtering *** restorationMenu = Menu(menu) menu.add_cascade(label='Restoration', menu=restorationMenu) restorationMenu.add_command(label="Full Inverse", command=self.fullInverseWrap) restorationMenu.add_command(label="Radially Limited Inverse", command=self.truncatedInverseWrap) restorationMenu.add_command(label="Approximate Weiner", command=self.approximateWeinerWrap) restorationMenu.add_command(label="Constrained LS", command=self.contrainedLSWrap) # ***** Toolbar ***** toolbar = Frame(master, bg="grey") undoButton = Button(toolbar, text="Undo", command=self.undoFunc) undoButton.pack(side=LEFT) origButton = Button(toolbar, text="Original", command=self.origFunc) origButton.pack(side=LEFT) toolbar.pack(side=TOP, fill=X) # ***** Image Display Area ***** self.frame = Frame(self.master) self.frame.pack() self.panel = Label(self.frame) self.panel.pack(padx=10, pady=10) self.img = None self.origImg = None self.prevImg = None # ***** Gamma Controls ***** self.gammaFrame = Frame(self.master) self.gammaSlider = Scale(self.gammaFrame, from_=0.1, to=2, orient=HORIZONTAL, resolution=0.1) self.gammaSlider.pack(side=TOP) self.gammaExitButton = Button(self.gammaFrame, text="Exit", command=self.gammaFrame.pack_forget) self.gammaExitButton.pack(side=TOP) # ***** Box Blur Controls ***** self.boxFrame = Frame(self.master) self.boxSlider = Scale(self.boxFrame, from_=1, to=5, orient=HORIZONTAL) self.boxSlider.pack(side=TOP) self.boxExitButton = Button(self.boxFrame, text="Exit", command=self.boxFrame.pack_forget) self.boxExitButton.pack(side=TOP) # ***** Truncated Inverse Controls ***** self.truncatedInverseFrame = Frame(self.master) self.truncatedInverseSlider = Scale(self.truncatedInverseFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.truncatedInverseSlider.pack(side=TOP) self.truncatedInverseExitButton = Button( self.truncatedInverseFrame, text="Exit", command=self.truncatedInverseFrame.pack_forget) self.truncatedInverseExitButton.pack(side=TOP) # ***** Weiner Controls ***** self.weinerFrame = Frame(self.master) self.weinerSlider = Scale(self.weinerFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.weinerSlider.pack(side=TOP) self.weinerExitButton = Button(self.weinerFrame, text="Exit", command=self.weinerFrame.pack_forget) self.weinerExitButton.pack(side=TOP) # ***** CLS Controls ***** self.clsFrame = Frame(self.master) self.clsSlider = Scale(self.clsFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.clsSlider.pack(side=TOP) self.clsExitButton = Button(self.clsFrame, text="Exit", command=self.clsFrame.pack_forget) self.clsExitButton.pack(side=TOP) # ***** DFT Display Area ****** self.dftFrame = Frame(self.master) self.magPanel = Label(self.dftFrame) self.magPanel.pack(padx=10, pady=10, side=TOP) self.freqPanel = Label(self.dftFrame) self.freqPanel.pack(padx=10, pady=10, side=TOP) self.dftExitButton = Button( self.dftFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.dftExitButton.pack(side=TOP, fill=X) # ***** Low Pass Mask Creation ***** self.lpmFrame = Frame(self.master) self.lpmPanel = Label(self.lpmFrame) self.lpmPanel.pack(padx=10, pady=10, side=TOP) self.lpmSubButton = Button(self.lpmFrame, text="submit") self.lpmSubButton.pack(side=TOP) self.lpmExitButton = Button( self.lpmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.lpmExitButton.pack(side=TOP) self.lpmSlider = Scale(self.lpmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** High Pass Mask Creation ***** self.hpmFrame = Frame(self.master) self.hpmPanel = Label(self.hpmFrame) self.hpmPanel.pack(padx=10, pady=10, side=TOP) self.hpmSubButton = Button(self.hpmFrame, text="submit") self.hpmSubButton.pack(side=TOP) self.hpmExitButton = Button( self.hpmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.hpmExitButton.pack(side=TOP) self.hpmSlider = Scale(self.hpmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** Band Pass Mask Creation ***** self.bppmFrame = Frame(self.master) self.bppmPanel = Label(self.bppmFrame) self.bppmPanel.pack(padx=10, pady=10, side=TOP) self.bppmSubButton = Button(self.bppmFrame, text="submit") self.bppmSubButton.pack(side=TOP) self.bppmExitButton = Button( self.bppmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.bppmExitButton.pack(side=TOP) self.bppmSliderLow = Scale(self.bppmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) self.bppmSliderHigh = Scale(self.bppmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** Band Pass Mask Creation ***** self.bspmFrame = Frame(self.master) self.bspmPanel = Label(self.bspmFrame) self.bspmPanel.pack(padx=10, pady=10, side=TOP) self.bspmSubButton = Button(self.bspmFrame, text="submit") self.bspmSubButton.pack(side=TOP) self.bspmExitButton = Button( self.bspmFrame, text="exit", command=lambda: self.displayImg(np.array(self.img))) self.bspmExitButton.pack(side=TOP) self.bspmSliderLow = Scale(self.bspmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) self.bspmSliderHigh = Scale(self.bspmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) def displayImg(self, img): # input image in RGB self.frame.pack() self.dftFrame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.img = Image.fromarray(img) imgtk = ImageTk.PhotoImage(self.img) self.panel.configure(image=imgtk) self.panel.image = imgtk def openImage(self): # can change the image path = filedialog.askopenfilename() if len(path) > 0: imgRead = cv2.imread(path) if imgRead is not None: imgRead = cv2.cvtColor(imgRead, cv2.COLOR_BGR2RGB) self.origImg = Image.fromarray(imgRead) self.prevImg = Image.fromarray(imgRead) self.displayImg(imgRead) else: raise ValueError("Not a valid image") else: raise ValueError("Not a valid path") def loadKernel(self): path = filedialog.askopenfilename() if len(path) > 0: self.filter_kernel = np.mean(cv2.imread(path), axis=-1) self.filter_kernel = self.filter_kernel / np.sum( self.filter_kernel) else: raise ValueError("Not a valid path") def saveImage(self): if self.img is not None: toSave = filedialog.asksaveasfilename() self.img.save(toSave) else: messagebox.showerror(title="Save Error", message="No image to be saved!") def histWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.histEqlFunc(img) self.displayImg(imgNew) # Gamma Correction def gammaCallback(self, event, img): gamma = self.gammaSlider.get() self.prevImg = self.img imgNew = image_utils.gammaCorFunc(img, 255.0 / (255.0**gamma), gamma) self.displayImg(imgNew) def truncatedInverseCallback(self, event, img): th = 10**self.truncatedInverseSlider.get() imgNew = self.truncatedInverseFilter(th) self.displayImg(imgNew) def weinerCallback(self, event, img): gamma = 10**self.weinerSlider.get() imgNew = self.weinerFilter(gamma) self.displayImg(imgNew) def clsCallback(self, event, img): K = 10**self.clsSlider.get() imgNew = self.clsFilter(K) self.displayImg(imgNew) def gammaCorWrap(self): img = np.array(self.img) self.gammaFrame.pack() self.gammaSlider.set(1.0) self.gammaSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.gammaCallback(event, img)) def logTranWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.logTranFunc(img, 255.0 / np.log10(256)) self.displayImg(imgNew) def sharpWrap(self): # Sharpen Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.sharpFunc(img) self.displayImg(imgNew) def boxBlurWrap(self): # Box Blur Wrapper img = np.array(self.img) self.prevImg = self.img self.boxFrame.pack() self.boxSlider.set(1) self.boxSlider.bind("<ButtonRelease-1>", lambda event, img=img: self.displayImg( image_utils.boxBlurFunc( event, img, 2 * self.boxSlider.get() + 1))) def gaussianBlurWrap(self): # Gaussian Blur Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.gaussianBlurFunc(img) self.displayImg(imgNew) def medianBlurWrap(self): # Median Blur Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.medianBlurFunc(img) self.displayImg(imgNew) def cartoonifyWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.cartoonifyFunc(img) self.displayImg(imgNew) def undoFunc(self): self.img = self.prevImg self.displayImg(np.array(self.img)) def origFunc(self): self.prevImg = self.img self.img = self.origImg self.displayImg(np.array(self.img)) def displayDFT(self, x_fft): m, n = x_fft.shape[:] self.frame.pack_forget() self.dftFrame.pack() x_mag = np.log10(np.absolute(x_fft)) * 255 / np.log10(m * n * 255) x_mag = Image.fromarray(x_mag) x_mag = x_mag.resize((min(256, m), min(int(256 * n / m), n)), Image.ANTIALIAS) x_mag = ImageTk.PhotoImage(x_mag) x_freq = (np.angle(x_fft) % 360) * 255 / 360 x_freq = Image.fromarray(x_freq) x_freq = x_freq.resize((min(256, m), min(int(256 * n / m), n)), Image.ANTIALIAS) x_freq = ImageTk.PhotoImage(x_freq) self.magPanel.configure(image=x_mag) self.magPanel.image = x_mag self.freqPanel.configure(image=x_freq) self.freqPanel.image = x_freq def dftWrap(self): img = np.array(self.img) x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) x_outp_img = fft.fft2d_img(x) self.displayDFT(x_outp_img) def freqMaskWrap(self): m, n = np.array(self.img).shape[:2] lm, ln = np.log2(m), np.log2(m) dm, dn = int(2**np.ceil(lm)) + 1, int(2**np.ceil(ln)) + 1 messagebox.showinfo( "Mask Size", "Mask Size should be (" + str(dm) + "," + str(dn) + ")") path = filedialog.askopenfilename() if len(path) > 0: maskRead = cv2.imread(path, 0) if (maskRead.shape != (dm, dn)): messagebox.showerror( title="Shape Error", message="Shape of mask and image don't match") else: self.prevImg = self.img self.display(image_utils.freqMask(np.array(self.img), maskRead)) else: raise ValueError("Not a valid path") def maskWrap(self): img = np.array(self.img) x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) x_outp_img = fft.fft2d_img(x) x_mag = image_utils.xMagCreate(x_outp_img) return x_outp_img, x_mag def maskFinal(self, x_outp_img): self.prevImg = self.img img = np.array(self.img) img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) m = len(img) res = fft.ifft2d_img(x_outp_img) res = np.array(res * 255 / np.max(res), dtype=np.uint8) res = np.array([[[img[i][j][0], img[i][j][1], res[i][j]] for j in range(m)] for i in range(m)]) res = cv2.cvtColor(res, cv2.COLOR_HSV2RGB) self.displayImg(res) def lpmCallBack(self, event, slider, x_outp_img): m = len(x_outp_img) m2 = int((m - 1) / 2) r = slider.get() x_outp_copy = np.copy(x_outp_img) nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(m)] for i in range(m)]) nCircle = np.where(nCircle > r**2) x_outp_copy[nCircle] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.lpmPanel.configure(image=x_mag) self.lpmPanel.image = x_mag def lpmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = self.lpmSlider.get() nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nCircle = np.where(nCircle > r**2) x_outp_img[nCircle] = 0 self.maskFinal(x_outp_img) def lpmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.lpmPanel.configure(image=x_mag) self.lpmPanel.image = x_mag self.lpmSlider.configure(to=int(np.ceil(m / 2))) self.lpmSlider.set(1) self.lpmSlider.pack(side=TOP) self.lpmSlider.bind( "<ButtonRelease-1>", lambda event, slider=self.lpmSlider, x_outp_img=x_outp_img: self. lpmCallBack(event, slider, x_outp_img)) self.lpmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.lpmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.lpmFrame.pack() def hpmCallBack(self, event, slider, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = slider.get() x_outp_copy = np.copy(x_outp_img) circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) circle = np.where(circle <= r**2) x_outp_copy[circle] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.hpmPanel.configure(image=x_mag) self.hpmPanel.image = x_mag def hpmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = self.hpmSlider.get() circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) circle = np.where(circle <= r**2) x_outp_img[circle] = 0 self.maskFinal(x_outp_img) def hpmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.hpmPanel.configure(image=x_mag) self.hpmPanel.image = x_mag self.hpmSlider.configure(to=m // 2) self.hpmSlider.set(1) self.hpmSlider.pack(side=TOP) self.hpmSlider.bind( "<ButtonRelease-1>", lambda event, slider=self.hpmSlider, x_outp_img=x_outp_img: self. hpmCallBack(event, slider, x_outp_img)) self.hpmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.hpmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.hpmFrame.pack() def bppmCallBack(self, event, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bppmSliderLow.get() r2 = self.bppmSliderHigh.get() assert (r1 <= r2) self.bppmSliderLow.configure(to=r2) self.bppmSliderHigh.configure(from_=r1) x_outp_copy = np.copy(x_outp_img) allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where(allVals < r1**2) x_outp_copy[nullVals] = 1 nullVals = np.where(allVals > r2**2) x_outp_copy[nullVals] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.bppmPanel.configure(image=x_mag) self.bppmPanel.image = x_mag def bppmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bppmSliderLow.get() r2 = self.bppmSliderHigh.get() allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where(allVals < r1**2) x_outp_img[nullVals] = 0 nullVals = np.where(allVals > r2**2) x_outp_img[nullVals] = 0 self.maskFinal(x_outp_img) def bppmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.bppmPanel.configure(image=x_mag) self.bppmPanel.image = x_mag self.bppmSliderHigh.configure(from_=1) self.bppmSliderHigh.configure(to=m // 2) self.bppmSliderHigh.set(m // 2) self.bppmSliderHigh.pack(side=TOP) self.bppmSliderHigh.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bppmCallBack(event, x_outp_img)) self.bppmSliderLow.configure(from_=1) self.bppmSliderLow.configure(to=m // 2) self.bppmSliderLow.set(1) self.bppmSliderLow.pack(side=TOP) self.bppmSliderLow.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bppmCallBack(event, x_outp_img)) self.bppmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.bppmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bspmFrame.pack_forget() self.bppmFrame.pack() def bspmCallBack(self, event, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bspmSliderLow.get() r2 = self.bspmSliderHigh.get() assert (r1 <= r2) self.bspmSliderLow.configure(to=r2) self.bspmSliderHigh.configure(from_=r1) x_outp_copy = np.copy(x_outp_img) allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0) x_outp_copy[nullVals] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.bspmPanel.configure(image=x_mag) self.bspmPanel.image = x_mag def bspmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bspmSliderLow.get() r2 = self.bspmSliderHigh.get() allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0) x_outp_img[nullVals] = 0 self.maskFinal(x_outp_img) def bspmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.bspmPanel.configure(image=x_mag) self.bspmPanel.image = x_mag self.bspmSliderHigh.configure(from_=1) self.bspmSliderHigh.configure(to=m // 2) self.bspmSliderHigh.set(m // 2) self.bspmSliderHigh.pack(side=TOP) self.bspmSliderHigh.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bspmCallBack(event, x_outp_img)) self.bspmSliderLow.configure(from_=1) self.bspmSliderLow.configure(to=m // 2) self.bspmSliderLow.set(1) self.bspmSliderLow.pack(side=TOP) self.bspmSliderLow.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bspmCallBack(event, x_outp_img)) self.bspmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.bspmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack() def fullInverseWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = filtering.inverseFilter2D(img, self.filter_kernel) self.displayImg(imgNew) def truncatedInverseWrap(self): img = np.array(self.img) self.prevImg = self.img self.truncatedInverseFilter = filtering.getTruncatedInverseFilter2D( img, self.filter_kernel) self.truncatedInverseFrame.pack() self.truncatedInverseSlider.set(1.0) self.truncatedInverseSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.truncatedInverseCallback(event, img)) def approximateWeinerWrap(self): img = np.array(self.img) self.prevImg = self.img self.weinerFilter = filtering.getApproximateWeinerFilter2D( img, self.filter_kernel) self.weinerFrame.pack() self.weinerSlider.set(1.0) self.weinerSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.weinerCallback(event, img)) def contrainedLSWrap(self): # TODO: implement img = np.array(self.img) self.prevImg = self.img self.clsFilter = filtering.getConstrainedLSFilter2D( img, self.filter_kernel) self.clsFrame.pack() self.clsSlider.set(1.0) self.clsSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.clsCallback(event, img))
class AuxMode(Frame): def __init__(self, root, parent): Frame.__init__(self, root, borderwidth=2, relief='groove', height=10) settings = parent.settings('aux_mode') self.parent = parent lbl_power = Label(self, text='Power:') lbl_power.grid(row=0, column=0, pady=2) self.cmb_power = ttk.Combobox(self, value=['Off', 'On']) self.cmb_power.grid(row=0, column=1, pady=2) self.cmb_power.set(settings['power']) self.cmb_power['state'] = 'readonly' self.cmb_power.bind('<<ComboboxSelected>>', self.set_power) lbl_aux_pin = Label(self, text='AUX pin:') lbl_aux_pin.grid(row=1, column=0, pady=2) self.cmb_aux_pin = ttk.Combobox(self, values=['AUX', 'CS']) self.cmb_aux_pin.grid(row=1, column=1, pady=2) self.cmb_aux_pin['state'] = 'readonly' self.cmb_aux_pin.set(settings['aux_pin']) self.cmb_aux_pin.bind('<<ComboboxSelected>>', self.select_aux_pin) lbl_aux = Label(self, text='AUX mode:') lbl_aux.grid(row=2, column=0, pady=2) self.cmb_aux_mode = ttk.Combobox( self, values=['Input', 'Output', 'Servo', 'PWM']) self.cmb_aux_mode.grid(row=2, column=1, pady=2) self.cmb_aux_mode['state'] = 'readonly' self.cmb_aux_mode.set(settings['mode']) self.cmb_aux_mode.bind('<<ComboboxSelected>>', self.select_aux_mode) self.aux_servo = Scale(self, from_=0, to=180, orient='horizontal') self.aux_servo.set(settings['servo']) self.aux_servo.bind('<ButtonRelease-1>', self.select_aux_mode) self.aux_pin_state = IntVar() self.aux_pin_state.set(settings['aux_state']) self.aux_pin_state.trace_add('write', self.select_aux_mode) self.aux_high = Radiobutton(self, text='HIGH', value=1, variable=self.aux_pin_state) self.aux_low = Radiobutton(self, text='LOW', value=0, variable=self.aux_pin_state) self.aux_pwm_lbl = Label(self, text='Frequency (KHz):') self.aux_pwm_freq = Entry(self) self.aux_pwm_freq.insert(0, settings['pwm_freq']) self.aux_pwm_freq.bind('<KeyRelease>', self.select_aux_mode) self.aux_pwm_duty_lbl = Label(self, text='Duty cycle (%):') self.aux_pwm_duty = Scale(self, from_=0, to=99, orient='horizontal') self.aux_pwm_duty.set(settings['pwm_duty']) self.aux_pwm_duty.bind('<ButtonRelease-1>', self.select_aux_mode) def __call__(self): return { 'power': self.cmb_power.get(), 'mode': self.cmb_aux_mode.get(), 'aux_state': self.aux_pin_state.get(), 'aux_pin': self.cmb_aux_pin.get(), 'servo': self.aux_servo.get(), 'pwm_freq': self.aux_pwm_freq.get(), 'pwm_duty': self.aux_pwm_duty.get() } def select_aux_mode(self, e=None, a=None, b=None): for i, widget in enumerate(self.winfo_children()): if i > 5: widget.grid_forget() mode = self.cmb_aux_mode.get() # if self.parent.console.mode == 'HiZ': return if mode == 'Input': self.parent.console.aux('Input') if mode == 'Output': self.aux_high.grid(row=3, column=1) self.aux_low.grid(row=4, column=1) self.parent.console.aux('Output', self.aux_pin_state.get()) if mode == 'Servo': self.aux_servo.grid(row=3, column=1) self.parent.console.servo(self.aux_servo.get()) if mode == 'PWM': self.aux_pwm_lbl.grid(row=3, column=0) self.aux_pwm_freq.grid(row=3, column=1) self.aux_pwm_duty_lbl.grid(row=4, column=0) self.aux_pwm_duty.grid(row=4, column=1) self.parent.console.pwm(self.aux_pwm_freq.get(), self.aux_pwm_duty.get()) if mode == 'CS': self.parent.console.cs() self.parent.settings('aux_mode', self()) def select_aux_pin(self, e=None): self.parent.console.aux_pin(self.cmb_aux_pin.get()) def set_power(self, e=None): self.parent.console.power(self.cmb_power.get()) self.parent.settings('aux_mode', self()) def disable(self): self.cmb_power['state'] = 'disabled' self.cmb_aux_mode['state'] = 'disabled' self.aux_high['state'] = 'disabled' self.aux_low['state'] = 'disabled' self.aux_servo['state'] = 'disabled' self.aux_pwm_freq['state'] = 'disabled' self.aux_pwm_duty['state'] = 'disabled' def enable(self): self.cmb_power['state'] = 'readonly' self.cmb_aux_mode['state'] = 'readonly' self.aux_high['state'] = 'normal' self.aux_low['state'] = 'normal' self.aux_servo['state'] = 'normal' self.aux_pwm_freq['state'] = 'normal' self.aux_pwm_duty['state'] = 'normal'
def main(): """ основной метод - создание графического интерфейса TKinter :return: """ global params window = Tk() window.title("Отражение в параболическом зеркале") window.geometry('500x400') canv = Frame(window) setup = LabelFrame(window, text='Настройки', width=450, height=150) c = Canvas(canv, width=450, height=230, bg='black') c.pack(side=TOP, padx=10) setup1 = Frame(setup) butFrame = Frame(setup1) scal = Scale(setup1, orient=HORIZONTAL, length=200, from_=0.002, to=0.01, tickinterval=0.002, resolution=0.002) scal.set(0.002) scal.pack(side=TOP, pady=(0, 10), padx=(10, 10)) scal.bind("<ButtonRelease-1>", lambda event, draw_canv=c: redraw(event, draw_canv)) Button(butFrame, text='Очистить', width=12, command=lambda event=None, draw_canv=c, flag=True: redraw(event, draw_canv, setarrow=flag)) \ .pack(side=LEFT, padx=(10, 5), pady=(5, 10)) Button(butFrame, text='Закрыть', width=12, command=lambda flag=0: sys.exit(flag)).pack(side=LEFT, padx=(5, 10), pady=(5, 10)) butFrame.pack(side=TOP) setup1.pack(side=LEFT) columns = ('#1', '#2') params = Treeview(setup, show='headings', columns=columns) params.heading('#1', text='Параметр') params.heading('#2', text='Значение') params.column('#1', width=100, minwidth=50, stretch=NO, anchor=N) params.column('#2', width=100, minwidth=50, stretch=NO, anchor=N) params.pack(side=LEFT, padx=(5, 10), pady=(0, 10)) canv.pack(side=TOP, pady=(10, 10)) setup.pack(side=TOP, pady=(0, 10), padx=(25, 25)) draw_parabola(c) window.bind('<Button-1>', press) window.bind('<ButtonRelease-1>', lambda event, draw_canv=c: release(event, draw_canv)) window.mainloop()
class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) self.master = master self.grid(padx=4, pady=0) self.window_width = 1850 self.window_height = 900 self._geom = '{x}x{y}+0+0'.format(x=self.window_width, y=self.window_height) self.master.geometry(self._geom) self.image_size = 450 self.canvases = dict() self.scale_value = DoubleVar() self.create_window() self.create_widgets() #fullscreen #pad = 3 #master.geometry("{0}x{1}+0+0".format( # master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad)) #master.bind('<Escape>',self.toggle_geom) def create_widgets(self): self.create_buttons() #self.create_scroll_bar() self.create_canvases() self.create_parameters_box() self.create_progressbar() self.set_default_values() def create_buttons(self): #upload button self.upload_input_button = tk.Button(self, text="Wgraj obraz", command=self.upload_input_file, width=50, height=3, fg='white', bg='green') self.upload_input_button.grid(row=12, column=0, pady=15) #transform start button self.start_transform_button = tk.Button(self, text="Uruchom tomograf", command=start_radon_transform, width=50, height=3, fg='white', bg='green') self.start_transform_button.grid(row=13, column=0, pady=15) def create_window(self): self.frame = Frame(self.master, width=self.window_width, height=self.window_height) def upload_input_file(self): filename = filedialog.askopenfilename(filetypes=[('Image', 'jpg jpeg png gif')]) if filename == "": return load_input_file(filename) img = Image.open(filename) self.set_image_on_canvas(img, ImageType.INPUT_IMAGE) self.reconstruction_progress['value'] = 0 def set_image_on_canvas(self, img, image_type): canvas = self.canvases[image_type] if type(img) is np.ndarray: img = Image.frombytes('L', (img.shape[1], img.shape[0]), img.astype('b').tostring()) img = img.resize((canvas.winfo_width(), canvas.winfo_height()), Image.ANTIALIAS) self.canvases[image_type].image = ImageTk.PhotoImage(img) self.canvases[image_type].create_image(0, 0, image=canvas.image, anchor=tk.NW) self.update() def create_canvases(self): x = 0 for i in ImageType: self.canvases[i] = Canvas(self, width=self.image_size, height=self.image_size, bg='white') self.canvases[i].create_rectangle(2, 2, self.image_size, self.image_size) self.canvases[i].create_text(self.image_size // 2, self.image_size // 2, text=text_values[i]) if i == ImageType.GRAPH: continue #self.canvases[i].grid(row=1, column=2, rowspan=15) else: self.canvases[i].grid(row=0, column=x) x += 1 def create_scroll_bar(self): self.scale = Scale(self, from_=0, to_=150, tickinterval=10, length=self.image_size - 20, variable=self.scale_value, orient=tk.HORIZONTAL) self.scale.bind("<ButtonRelease-1>", method) self.scale.set(0) self.scale.grid(row=2, column=2) def create_parameters_box(self): default_font = ("Helvetica", 9) #error label self.error = tk.StringVar() tk.Label(self, textvariable=self.error, fg="red", font=("Helvetica", 16)).grid(row=2) tk.Label(self, text="Liczba emiterów", font=default_font).grid(row=3, sticky='w') self.detectors_number = tk.Entry(self, width=4, justify=tk.RIGHT) self.detectors_number.grid(row=3) tk.Label(self, text="Rozpiętość kątowa", font=default_font).grid(row=4, sticky='w') self.emission_angle = tk.Entry(self, width=4, justify=tk.RIGHT) self.emission_angle.grid(row=4) tk.Label(self, text="Obrót tomografu", font=default_font).grid(row=5, sticky='w') self.radon_angle = tk.Entry(self, width=4, justify=tk.RIGHT) self.radon_angle.grid(row=5) tk.Label(self, text="Krok", font=default_font).grid(row=6, sticky='w') self.step_angle = tk.Entry(self, width=4, justify=tk.RIGHT) self.step_angle.grid(row=6) self.sinogram_convolution = tkinter.IntVar(value=1) self.sinogram_convoltion_checkbox = tk.Checkbutton( self, text="Użyj splotu przy sinorgamie", variable=self.sinogram_convolution, command=self.update_options) self.sinogram_convoltion_checkbox.grid(row=7, sticky='w') self.use_parallel_rays = tkinter.IntVar(value=1) self.parallel_rays_checkbox = tk.Checkbutton( self, text="Użyj promieni równoległych", variable=self.use_parallel_rays, command=self.update_options) self.parallel_rays_checkbox.grid(row=8, sticky='w') self.use_fourier = tkinter.IntVar(value=1) self.fourier_checkbox = tk.Checkbutton( self, text="Użyj rekonstrukcji Fouriera", variable=self.use_fourier, command=self.update_options) self.fourier_checkbox.grid(row=9, sticky='w') self.use_convolution_at_end = tkinter.IntVar(value=1) self.convolution_end_checkbutton = tk.Checkbutton( self, text="Użyj splotu na wyjściu", variable=self.use_convolution_at_end, command=self.update_options) self.convolution_end_checkbutton.grid(row=10, sticky='w') def set_default_values(self): self.sinogram_convolution.set(1 if main.use_convolution_filter else 0) self.use_parallel_rays.set(1 if main.parallel_rays_mode else 0) self.use_convolution_at_end.set( 1 if main.use_convolution_in_output else 0) self.use_fourier.set(1 if main.use_fourier_reconstruction else 0) self.detectors_number.insert(tk.END, main.n_detectors) self.radon_angle.insert(tk.END, main.radon_angle) self.emission_angle.insert(tk.END, main.emission_angle) self.step_angle.insert(tk.END, main.step_angle) self.reset_progressbar() def update_options(self): main.use_convolution_in_output = False if self.use_convolution_at_end.get( ) == 0 else True main.use_fourier_reconstruction = False if self.use_fourier.get( ) == 0 else True main.use_convolution_filter = False if self.sinogram_convolution.get( ) == 0 else True main.parallel_rays_mode = False if self.use_parallel_rays.get( ) == 0 else True def create_progressbar(self): self.reconstruction_progress = ttk.Progressbar(self, orient="horizontal", length=self.image_size, mode="determinate") self.reconstruction_progress.grid(row=1, column=3, rowspan=2) def reset_progressbar(self): self.reconstruction_progress['value'] = 0 ratio = main.radon_angle // main.step_angle * main.step_angle self.reconstruction_progress['maximum'] = ratio
st.set('0') ptscln.set('-1') ptsclb = BooleanVar() # 是否正在拖拽进度条 ptsclb.set(False) liststatuscode = IntVar() liststatuscode.set(0) ptlb = Label(duf, text=mtt) # 总时长显示,↓进度条 ptscl = Scale(duf, length=170, orient=HORIZONTAL, from_=0, to=0, showvalue=False, command=ptscl1) ptscl.bind('<1>', ptscl0) ptscl.bind('<ButtonRelease-1>', ptscl2) listbutton = Button(duf, text='列表循环', command=liststatus) prebutton = Button(duf, text='⏮', command=playlastmusic) nextbutton = Button(duf, text='⏭', command=playnextmusic_) ptlb.pack(side=LEFT) ptscl.pack(side=LEFT) prebutton.pack(side=LEFT) listbutton.pack(side=LEFT) nextbutton.pack(side=LEFT) duf.pack(side=TOP) # 第四区块(音乐列表) lbrf = Frame(t) lbrsb = Scrollbar(lbrf) # 列表侧滚轮 lbrsb.pack(side=RIGHT, fill=Y)
class GraphicalInterface(): def __init__(self, *args, **kwargs): threading.Thread.__init__(self) self.kwargs = kwargs self.enable_joysticks = True if 'enable_joysticks' in self.kwargs: self.enable_joysticks = self.kwargs['enable_joysticks'] logging.getLogger("requests").setLevel(logging.WARNING) self.stop_robot = False self.logger = logging.getLogger('GUI') self.curr_image = None self.joint_states = [] self.num_empty_commands = 0 self.robot_ctrl = RobotController.getInstance(*args, **kwargs) self.logger.info('initializing robot...') self.robot_ctrl.init_robot() self.logger.info('robot successfully initilized') if 'robot_init_pos' in self.kwargs: self.logger.info('Sending robot to center.') self.robot_ctrl.send_robot_to_center(goal=kwargs['robot_init_pos']) self.logger.info('Robot centered.') np.set_printoptions(precision=2) self.image_size = (640, 360) if 'image_size' in self.kwargs: self.image_size = self.kwargs['image_size'] def callback(self): self.parent.quit() def run(self): self.parent = tk.Tk() self.main_frame = Frame(self.parent) self.main_frame.pack() if self.enable_joysticks: self.create_widgets() self.robot_controller() # def signal_handler(sig, frame): # self.logger.info('You pressed Ctrl+C') # # cap.release() # cv2.destroyAllWindows() # self.logger.info("Stopping Robot...") # self.stop_robot = True # self.robot_ctrl.send_joint_command_to_robot([0, 0, 0, 0, 0, 0], use_thread=False) # sys.exit(0) # signal.signal(signal.SIGINT, signal_handler) self.parent.mainloop() def robot_controller(self): self.curr_image = self.robot_ctrl.get_image_cv2() if self.curr_image is None: self.parent.after(10, self.robot_controller) return img = cv2.resize(self.curr_image, self.image_size) cv2.imshow('frame', img / 255.0) if cv2.waitKey(1) & 0xFF == ord('q'): return if self.stop_robot == True: return if self.enable_joysticks: x = -self.canvas.joystick_x y = -self.canvas.joystick_y v = (100 - abs(x)) * (y / 100) + y w = (100 - abs(y)) * (x / 100) + x x = (v - w) // 2 y = (v + w) // 2 command_to_send = [ x, y, self.scale1.get(), self.scale2.get(), self.scale4.get(), self.scale3.get() ] self.robot_ctrl.send_joint_command_to_robot(command_to_send) # self.robot_ctrl.update_joint_states() self.parent.after(10, self.robot_controller) def create_widgets(self): self.main_frame.style = ttk.Style() self.main_frame.winfo_toplevel().title("Nabot Controls") self.main_frame.style.theme_use('default') self.main_frame.configure(background='black') def create_canvas(): class Joystick(tk.Canvas): pass self.canvas = Joystick(self.main_frame, width=400, height=400) self.canvas.joystick_x = 0 self.canvas.joystick_y = 0 self.canvas.is_moving = False def paint(event): # self.canvas.create_rectangle(0, 0, 200, 200, fill='red') reset_canvas() self.canvas.create_oval(0, 0, 400, 400, fill='black', outline='gray') x1, y1 = event.x - 75, event.y - 75 x2, y2 = event.x + 75, event.y + 75 self.canvas.create_oval(x1, y1, x2, y2, fill='blue') self.canvas.joystick_x = (event.x - 200) * 7 / 10 self.canvas.joystick_y = (event.y - 200) * 7 / 10 self.canvas.joystick_x = min(max(self.canvas.joystick_x, -100), 100) self.canvas.joystick_y = min(max(self.canvas.joystick_y, -100), 100) def reset(event): self.canvas.is_moving = False self.canvas.joystick_x = 0 self.canvas.joystick_y = 0 reset_canvas() logging.debug('move the robot, x:{} y:{}'.format( self.canvas.joystick_x, self.canvas.joystick_y)) def reset_canvas(): self.canvas.create_rectangle(0, 0, 400, 400, fill='black') self.canvas.create_oval(0, 0, 400, 400, fill='black', outline='gray') self.canvas.create_oval(125, 125, 275, 275, fill='gray') self.canvas.pack(side='left') # self.canvas.bind('<Button-1>', start) self.canvas.bind('<B1-Motion>', paint) self.canvas.bind('<ButtonRelease-1>', reset) reset_canvas() def scale1_command(val): val = self.scale1.get() def scale1_stop(event): self.scale1.set(0) self.scale1 = Scale(from_=100, to=-100, label='head', command=scale1_command) self.scale1.bind('<ButtonRelease-1>', scale1_stop) self.scale1.pack(side='left') def scale2_command(val): val = self.scale2.get() def scale2_stop(event): self.scale2.set(0) self.scale2 = Scale(from_=100, to=-100, label='elbow', command=scale2_command) self.scale2.bind('<ButtonRelease-1>', scale2_stop) self.scale2.pack(side='left') self.scale3 = Scale(from_=0, to=100, orient=HORIZONTAL, label='Gripper') self.scale3.pack(side='top') def scale4_command(val): val = self.scale4.get() def scale4_stop(event): self.scale4.set(0) self.scale4 = Scale(from_=-100, to=100, orient=HORIZONTAL, command=scale4_command, label='wrist') self.scale4.bind('<ButtonRelease-1>', scale4_stop) self.scale4.pack(side='top') create_canvas()
class FilterFrame(Toplevel): def __init__(self, master=None): Toplevel.__init__(self, master=master) self.original_image = self.master.processed_image self.filtered_image = None self.negative_button = Button(master=self, text="Negative") self.black_white_button = Button(master=self, text="Black White") self.sepia_button = Button(master=self, text="Sepia") self.sepia_label = Label(self, text="Sepia") self.sepia_scale = Scale(self, from_=-200, to_=200, length=250, resolution=1, orient=HORIZONTAL) self.emboss_label = Label(self, text="Emboss") self.emboss_scale = Scale(self, from_=-200, to_=200, length=250, resolution=1, orient=HORIZONTAL) self.gaussian_blur_label = Label(self, text="Gaussian Blur") self.gaussian_blur_scale = Scale(self, from_=0, to_=10, length=250, resolution=1, orient=HORIZONTAL) # self.gaussian_blur_button = Button(master=self, text="Gaussian Blur") self.cancel_button = Button(master=self, text="Cancel") self.apply_button = Button(master=self, text="Apply") self.negative_button.bind("<ButtonRelease>", self.negative_button_released) self.black_white_button.bind("<ButtonRelease>", self.black_white_released) self.sepia_scale.bind("<ButtonRelease>", self.sepia_scale_released) self.emboss_scale.bind("<ButtonRelease>", self.emboss_scale_released) self.gaussian_blur_scale.bind("<ButtonRelease>", self.gaussian_blur_scale_released) # self.gaussian_blur_button.bind("<ButtonRelease>", self.gaussian_blur_button_released) self.apply_button.bind("<ButtonRelease>", self.apply_button_released) self.cancel_button.bind("<ButtonRelease>", self.cancel_button_released) self.negative_button.pack() self.black_white_button.pack() self.sepia_label.pack() self.sepia_scale.pack() self.emboss_label.pack() self.emboss_scale.pack() self.gaussian_blur_scale.pack() # self.gaussian_blur_button.pack() self.cancel_button.pack(side=RIGHT) self.apply_button.pack() def negative_button_released(self, event): self.negative() self.show_image() def black_white_released(self, event): self.black_white() self.show_image() def sepia_scale_released(self, event): self.sepia() self.show_image() def emboss_button_released(self, event): self.emboss() self.show_image() def emboss_scale_released(self, event): self.emboss() self.show_image() def gaussian_blur_scale_released(self, event): self.gaussian_blur() self.show_image() def apply_button_released(self, event): self.master.processed_image = self.filtered_image self.show_image() self.close() def cancel_button_released(self, event): self.master.image_viewer.show_image() self.close() def show_image(self): self.master.image_viewer.show_image(img=self.filtered_image) def negative(self): self.filtered_image = cv2.bitwise_not(self.original_image) def black_white(self): self.filtered_image = cv2.cvtColor(self.original_image, cv2.COLOR_BGR2GRAY) self.filtered_image = cv2.cvtColor(self.filtered_image, cv2.COLOR_GRAY2BGR) def sepia(self): kernel = np.array([[0.272, 0.534, 0.131], [0.349, 0.686, 0.168], [0.393, 0.769, 0.189]]) self.filtered_image = cv2.filter2D(self.original_image, -1, kernel, delta=self.sepia_scale.get()) def emboss(self): kernel = np.array([[0, -1, -1], [1, 0, -1], [1, 1, 0]]) self.filtered_image = cv2.filter2D(self.original_image, -1, kernel, delta=self.emboss_scale.get()) def gaussian_blur(self): size = self.gaussian_blur_scale.get() * 10 + 1 self.filtered_image = cv2.GaussianBlur(self.original_image, (size, size), 0) def close(self): self.destroy()
class AdjustFrame(Toplevel): def __init__(self, master=None): Toplevel.__init__(self, master=master) self.brightness_value = 0 self.previous_brightness_value = 0 self.original_image = self.master.processed_image self.processing_image = self.master.processed_image self.brightness_label = Label(self, text="Brightness") self.brightness_scale = Scale(self, from_=0, to_=2, length=250, resolution=0.1, orient=HORIZONTAL) self.r_label = Label(self, text="R") self.r_scale = Scale(self, from_=-100, to_=100, length=250, resolution=1, orient=HORIZONTAL) self.g_label = Label(self, text="G") self.g_scale = Scale(self, from_=-100, to_=100, length=250, resolution=1, orient=HORIZONTAL) self.b_label = Label(self, text="B") self.b_scale = Scale(self, from_=-100, to_=100, length=250, resolution=1, orient=HORIZONTAL) self.apply_button = Button(self, text="Apply") self.cancel_button = Button(self, text="Cancel") self.brightness_scale.set(1) self.apply_button.bind("<ButtonRelease>", self.apply_button_released) self.brightness_scale.bind("<ButtonRelease>", self.show_button_release) self.r_scale.bind("<ButtonRelease>", self.show_button_release) self.g_scale.bind("<ButtonRelease>", self.show_button_release) self.b_scale.bind("<ButtonRelease>", self.show_button_release) self.cancel_button.bind("<ButtonRelease>", self.cancel_button_released) self.brightness_label.pack() self.brightness_scale.pack() self.r_label.pack() self.r_scale.pack() self.g_label.pack() self.g_scale.pack() self.b_label.pack() self.b_scale.pack() self.cancel_button.pack(side=RIGHT) self.apply_button.pack() def apply_button_released(self, event): self.master.processed_image = self.processing_image self.close() def show_button_release(self, event): self.processing_image = cv2.convertScaleAbs( self.original_image, alpha=self.brightness_scale.get()) b, g, r = cv2.split(self.processing_image) for b_value in b: cv2.add(b_value, self.b_scale.get(), b_value) for g_value in g: cv2.add(g_value, self.g_scale.get(), g_value) for r_value in r: cv2.add(r_value, self.r_scale.get(), r_value) self.processing_image = cv2.merge((b, g, r)) self.show_image(self.processing_image) def cancel_button_released(self, event): self.close() def show_image(self, img=None): self.master.image_viewer.show_image(img=img) def close(self): self.show_image() self.destroy()
class GradientKit(Frame): """ Gradient Kit Frame - it manages gradient pattern. Gradient pattern allows modification of arrays. Parameters: - Minimum value gradient's radius: radius for max weakening of array's values - Maximum value gradient's radius: radius for max magnifying of array's values """ def __init__(self, parent): Frame.__init__(self, parent, bd=1, relief=SUNKEN) self.root = parent.master self.main_bg = parent['bg'] self.config(bg=self.main_bg) # basic array for faster response of changing pattern's parameters, but it takes 2x RAM! self.circle_basic_array = None self.array = None self.slider_events = ["<ButtonRelease-1>", "<ButtonRelease-3>"] # gradient menu self.generate_btn = Button(self, text="Make gradient", command=self.generate_gradient) self.generate_btn.grid(row=0, column=0, padx=5, pady=5, sticky='nw') self.show_btn = Button(self, text="Show gradient", command=self.show_array) self.show_btn.grid(row=0, column=1, padx=5, pady=5, sticky='nw') self.show_btn.grid_remove() self.clear_btn = Button(self, text="Clear gradient", command=self.clear_gradient, bg='darkred', fg='lightgray') self.clear_btn.grid(row=0, column=2, padx=5, pady=5, sticky='nw') self.clear_btn.grid_remove() # sliders - radius range 0-1 where 0 is exact middle of array and 1 is the most far corner self.min_value_radius = Scale(self, from_=0, to=1, resolution=0.01, length=275, orient=HORIZONTAL, label="Minimum value gradient's radius") self.min_value_radius.grid(row=1, column=0, padx=5, pady=5, columnspan=3) for event in self.slider_events: self.min_value_radius.bind(event, self.change_factor_event) self.max_value_radius = Scale(self, from_=0, to=1, resolution=0.01, length=275, orient=HORIZONTAL, label="Maximum value gradient's radius") self.max_value_radius.grid(row=2, column=0, padx=5, pady=5, columnspan=3) for event in self.slider_events: self.max_value_radius.bind(event, self.change_factor_event) self.max_value_radius.set(1) def change_factor_event(self, event): if self.array is not None: self.generate_gradient() def generate_gradient(self, refresh_map=True): if self.circle_basic_array is None \ or shape(self.circle_basic_array)[0] != self.root.MAP_SIZE[0]\ or shape(self.circle_basic_array)[1] != self.root.MAP_SIZE[1]: self.circle_basic_array = empty(self.root.MAP_SIZE, dtype=float) for i in range(self.root.MAP_SIZE[0] // 2): a = self.root.MAP_SIZE[0] // 2 - i for j in range(self.root.MAP_SIZE[1] // 2): # old squared gradient formula: x = i if i < j else j b = self.root.MAP_SIZE[1] // 2 - j x = -sqrt(a * a + b * b) self.circle_basic_array[i][j] = x self.circle_basic_array[i][self.root.MAP_SIZE[1] - j - 1] = x self.circle_basic_array[self.root.MAP_SIZE[0] - i - 1][j] = x self.circle_basic_array[self.root.MAP_SIZE[0] - i - 1][self.root.MAP_SIZE[1] - j - 1] = x if self.max_value_radius.get() < self.min_value_radius.get(): # allowing reversing gradient pattern (middle is suppressed instead of borders) self.array = 1 - self.circle_basic_array else: self.array = self.circle_basic_array.copy() # convert radius into array index x_of_border = int(self.root.MAP_SIZE[0] * (1 - self.max_value_radius.get()) / 2) y_of_border = int(self.root.MAP_SIZE[1] * (1 - self.max_value_radius.get()) / 2) self.array[self.array < self.array[x_of_border, y_of_border]] = \ self.array[x_of_border, y_of_border] if self.max_value_radius.get() == self.min_value_radius.get(): # in case of equal values, make sure indexes differ at least by 1 (pattern gets blank otherwise) x_of_border += 1 y_of_border += 1 else: x_of_border = int(self.root.MAP_SIZE[0] * (1 - self.min_value_radius.get()) / 2) y_of_border = int(self.root.MAP_SIZE[1] * (1 - self.min_value_radius.get()) / 2) self.array[self.array > self.array[x_of_border, y_of_border]] = \ self.array[x_of_border, y_of_border] # normalize values to the range: 0-1 if self.array.ptp(): self.array = ((self.array - amin(self.array)) / self.array.ptp()) if refresh_map: if self.root.img is None or self.root.displayed_frame is self: self.show_array() elif self.root.displayed_frame is self.root: self.root.display_map() self.show_btn.grid() self.clear_btn.grid() def show_array(self): # normalize values to 0-levels and rescale to 0-255 (grayscale) noise_map = (self.array * self.root.levels).astype(int) / self.root.levels * 255 self.root.img = ImageTk.PhotoImage(image=Image.fromarray(noise_map)) self.root.canvas.itemconfig(self.root.map_img, image=self.root.img) self.root.displayed_frame = self def clear_gradient(self): self.show_btn.grid_remove() self.clear_btn.grid_remove() self.array = None self.root.display_map()
class Window(object): """"This class creates a GUI using the built in python libary tkinter""" def __init__(self, window): self.window = window self.check = False self.animateval = False titlel = Label(window, text="Evolutionary Spatial Games", height=3) titlel.grid(row=0, column=0, rowspan=2) self.cellularAutomata = Canvas(window, height=600, width=600, background="blue") self.cellularAutomata.grid(row=2, column=0, rowspan="20") l2 = Label(window, text="Payoff matrix:", width=16) l2.grid(row=3, column=1) l3 = Label(window, text="Cell size: ", width=16) l3.grid(row=6, column=1) l8 = Label(window, text="Moore Neighbourhood: ", width=22) l8.grid(row=7, column=1) l9 = Label(window, text="Von Nuemann Neighbourhood: ", width=26) l9.grid(row=8, column=1) l4 = Label(window, text="Initial Distribution: ", width=16) l4.grid(row=10, column=1) l9 = Label(window, text="Fixed boundary (A): ", width=26) l9.grid(row=11, column=1) l9 = Label(window, text="Reflective boundary: ", width=26) l9.grid(row=12, column=1) l9 = Label(window, text="Periodic boundary: ", width=26) l9.grid(row=13, column=1) la = Label(window, text="Count (A|B|C): ", width=16) la.grid(row=16, column=1) l5 = Label(window, text="Iterations: ", width=16) l5.grid(row=17, column=1) b1 = Button(window, text="Draw", command=self.draw_command) b1.grid(row=19, column=1) self.b2 = Button(window, text="Start", command=self.begin_command) self.b2.grid(row=19, column=2) self.e1 = Scale( window, width=8, orient=HORIZONTAL, from_=2, to=3, label="Strategies" ) self.e1.grid(row=0, column=1) self.e1.bind("<ButtonRelease-1>", self.change_entry) self.li = Label(window, text="B invades A: ", width=16) self.li.grid(row=14, column=1) self.ival = IntVar() self.iv = Checkbutton(window, variable=self.ival) self.iv.grid(row=14, column=2) self.ld = Label(window, text="Dynamic", width=16) self.ld.grid(row=15, column=1) self.dyval = IntVar() self.dyval.set(1) self.dy = Checkbutton(window, variable=self.dyval) self.dy.grid(row=15, column=2) self.e2 = IntVar() self.e2 = Entry(window, textvariable=self.e2, width=6) self.e2.grid(row=3, column=2) self.e3 = IntVar() self.e3 = Entry(window, textvariable=self.e3, width=6) self.e3.grid(row=3, column=3) self.e4 = IntVar() self.e4 = Entry(window, textvariable=self.e4, width=6) self.e4.grid(row=4, column=2) self.e5 = IntVar() self.e5 = Entry(window, textvariable=self.e5, width=6) self.e5.grid(row=4, column=3) self.cellsize = IntVar() self.cellsize.set(8) self.cellsize = Entry(window, textvariable=self.cellsize, width=6) self.cellsize.grid(row=6, column=2) self.p1 = DoubleVar() self.p1 = Entry(window, textvariable=self.p1, width=6) self.p1.grid(row=10, column=2) self.p2 = DoubleVar() self.p2 = Entry(window, textvariable=self.p2, width=6) self.p2.grid(row=10, column=3) self.neighbourE = IntVar() self.neighbourE.set(1) self.moore = Radiobutton(window, variable=self.neighbourE, value=1) self.moore.grid(row=7, column=2) self.nuemann = Radiobutton(window, variable=self.neighbourE, value=2) self.nuemann.grid(row=8, column=2) self.boundaryvar = IntVar() self.boundaryvar.set(2) self.fixed = Radiobutton(window, variable=self.boundaryvar, value=1) self.fixed.grid(row=11, column=2) self.reflective = Radiobutton(window, variable=self.boundaryvar, value=2) self.reflective.grid(row=12, column=2) self.periodic = Radiobutton(window, variable=self.boundaryvar, value=3) self.periodic.grid(row=13, column=2) self.a1 = Listbox(window, width=4, height=1) self.a1.grid(row=16, column=2) self.a2 = Listbox(window, width=4, height=1) self.a2.grid(row=16, column=3) self.i1 = Listbox(window, width=4, height=1) self.i1.grid(row=17, column=2) def draw_command(self): self.cellularAutomata.delete("all") self.count = 0 self.i1.delete(0, END) self.i1.insert(END, self.count) try: self.b3.destroy() self.b2 = Button(window, text="Start", command=self.begin_command) self.b2.grid(row=19, column=2) except AttributeError: pass try: if self.e1.get() == 2: matrix = [ [self.e2.get(), self.e3.get()], [self.e4.get(), self.e5.get()], ] self.SpatialGame = spatialGame( 600, 600, self.cellsize.get(), [self.p1.get(), self.p2.get()], self.e1.get(), matrix, self.ival.get(), self.neighbourE.get(), self.boundaryvar.get(), self.dyval.get(), ) if self.e1.get() == 3: matrix = [ [self.e2.get(), self.e3.get(), self.e6.get()], [self.e4.get(), self.e5.get(), self.e7.get()], [self.e8.get(), self.e9.get(), self.e10.get()], ] self.SpatialGame = spatialGame( 600, 600, self.cellsize.get(), [self.p1.get(), self.p2.get(), self.p3.get()], self.e1.get(), matrix, self.ival.get(), self.neighbourE.get(), self.boundaryvar.get(), self.dyval.get(), ) self.cells = self.SpatialGame.cells for x in range(0, self.SpatialGame.width): for y in range(0, self.SpatialGame.height): if self.cells[x][y] == 2: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="red", outline="red" ) if self.SpatialGame.cells[x][y] == 3: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="pink", outline="pink" ) except ValueError: self.cellularAutomata.create_text( 300, 300, fill="White", font="Times 20 bold", text="Your probability distribution must add to 1.", ) def begin_command(self): self.animateval = True self.animate() def next(self): self.cellularAutomata.delete("all") self.SpatialGame.run_rules() self.cells = self.SpatialGame.cells self.count = self.count + 1 self.i1.delete(0, END) self.i1.insert(END, self.count) self.b2.destroy() self.b3 = Button(window, text="Stop", command=self.stop_command) self.b3.grid(row=19, column=2) self.animateval = True for x in range(0, self.SpatialGame.width): for y in range(0, self.SpatialGame.height): if self.cells[x][y] == 2: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="red", outline="red" ) if self.cells[x][y] == 4: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="green", outline="green" ) if self.cells[x][y] == 5: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="yellow", outline="yellow" ) if self.cells[x][y] == 3: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="pink", outline="pink" ) if self.cells[x][y] == 6: square_coords = ( x * self.SpatialGame.cell_size, y * self.SpatialGame.cell_size, x * self.SpatialGame.cell_size + self.SpatialGame.cell_size, y * self.SpatialGame.cell_size + self.SpatialGame.cell_size, ) self.cellularAutomata.create_rectangle( square_coords, fill="purple", outline="purple" ) self.a1.delete(0, END) self.a1.insert(END, self.SpatialGame.stratA) self.a2.delete(0, END) self.a2.insert(END, self.SpatialGame.stratB) try: self.a3.delete(0, END) self.a3.insert(END, self.SpatialGame.stratC) except: pass def change_entry(self, event): if self.e1.get() == 3 and self.check == False: self.check = True self.e6 = IntVar() self.e6 = Entry(window, textvariable=self.e6, width=6) self.e6.grid(row=3, column=4) self.e7 = IntVar() self.e7 = Entry(window, textvariable=self.e7, width=6) self.e7.grid(row=4, column=4) self.e8 = IntVar() self.e8 = Entry(window, textvariable=self.e8, width=6) self.e8.grid(row=5, column=2) self.e9 = IntVar() self.e9 = Entry(window, textvariable=self.e9, width=6) self.e9.grid(row=5, column=3) self.e10 = IntVar() self.e10 = Entry(window, textvariable=self.e10, width=6) self.e10.grid(row=5, column=4) self.p3 = DoubleVar() self.p3 = Entry(window, textvariable=self.p3, width=6) self.p3.grid(row=10, column=4) self.li.destroy() self.iv.destroy() self.ival = IntVar() self.ival.set(0) self.a3 = Listbox(window, width=4, height=1) self.a3.grid(row=16, column=4) elif self.e1.get() == 2 and self.check == True: self.li = Label(window, text="B invades A: ", width=16) self.li.grid(row=14, column=1) self.ival = IntVar() self.iv = Checkbutton(window, variable=self.ival) self.iv.grid(row=14, column=2) self.check = False self.e6.destroy() self.e7.destroy() self.e8.destroy() self.e9.destroy() self.e10.destroy() self.p3.destroy() self.a3.destroy() def stop_command(self): self.animateval = False self.b3.destroy() self.b2 = Button(window, text="Start", command=self.begin_command) self.b2.grid(row=19, column=2) def animate(self): while self.animateval == True: self.next() self.window.update() time.sleep(0.5)
boton.place (relx=0.5, rely=0.32, anchor=CENTER) # Etiqueta que contiene la cantidad de iteraciones realizadas para el cálculo. etiqueta = Label (ventana, text = ('Iteraciones necesarias: ' + str (iteracionesTotales))) etiqueta.config (bg = 'white', font = ('Verdana', 15)) etiqueta.place (relx=0.5, rely=0.37, anchor=CENTER) #Función que permite graficar a tiempo real. Esta ejecuta nuevamente la función Graficar para realizar nuevamente el cálculo. animation.FuncAnimation (fig, Graficar, interval = 1000) plt.close () # Se define el slider para el tamaño del lado. barraL = Scale(ventana, from_=7, to=20, tickinterval=13, length=400, bg = 'White', resolution=1, showvalue=True, orient='horizontal', label="Tamaño del Lado (Lx)", cursor = "hand1") barraL.bind ("<ButtonRelease-1>",Graficar) barraL.set(10) barraL.place (relx=0.175, rely=0.05, anchor=CENTER) # Se define el slider para el tiempo a evaluar. barraTiempos = Scale(ventana, from_=1, to=5, tickinterval=4,length=400, bg = 'White', resolution=0.5, showvalue=True, orient='horizontal', label="Tiempo (s)", cursor = "hand1") barraTiempos.bind ("<ButtonRelease-1>",Graficar) barraTiempos.set(3) barraTiempos.place (relx=0.5, rely=0.05, anchor=CENTER) # Se define el slider para el número de términos. barraPresición = Scale(ventana, from_=0.001, to=1, tickinterval=0.999,length=400, bg = 'White', resolution=0.001, showvalue=True, orient='horizontal', label="Presición", cursor = "hand1")
root.resizable(False, False) root.wm_attributes("-topmost", 1) # uses xrandr to get current output currentOutput = str( popen('xrandr | grep " connected" | cut -f1 -d " " ').read()).strip() print(currentOutput) def setBrightness(event, limiter=0.2): _level = level.get( ) / 100 # scale returns value from 0 - 100 must be converted to decimal print(_level) # limits darkest setting to 20% to prevent user from completly blacking out moniter if _level <= limiter: _level = limiter system(f'xrandr --output {currentOutput} --brightness {_level}') level = Scale(root, from_=100, to_=0) level.set( float( popen("xrandr --verbose | awk '/Brightness/ { print $2; exit }'").read( )) * 100) # sets scale slider to current brightness level.bind("<ButtonRelease-1>", setBrightness) level.pack() root.mainloop()
class HOPSFitsWindow(HOPSWidget): def __init__(self, window, input=None, input_name=None, input_options=None, figsize=None, show_nav=False, show_controls=False, show_axes=False, subplots_adjust=None, dwmax=8.0, dhmax=8.0): widget = Frame(window.main_frame) self.show_axes = show_axes if figsize: try: wpcent, hpcent, wmax, hmax, ratio, = figsize wmax, hmax = dwmax, dhmax w = min(wpcent * window.log.plt2screen_w, wmax) h = min(hpcent * window.log.plt2screen_h, hmax) if h * ratio < w: w = h * ratio else: h = w / ratio except: w, h = figsize self.figure = matplotlib.figure.Figure(figsize=(w, h)) else: self.figure = matplotlib.figure.Figure() self.figure.patch.set_facecolor('white') self.canvas = FigureCanvasTkAgg(self.figure, widget) self.ax = self.figure.add_subplot(111) self.ax.tick_params(axis='y', rotation=90) if not self.show_axes: self.ax.axis('off') self.figure.subplots_adjust(left=0.01, right=0.99, bottom=0.01, top=0.99) if subplots_adjust: self.figure.subplots_adjust(left=subplots_adjust[0], right=subplots_adjust[1], bottom=subplots_adjust[2], top=subplots_adjust[3]) self.data = None self.mean = 0 self.std = 0 self.image = None self.sqrt_vmin = DoubleVar(widget, value=0) self.vmin = IntVar(widget, value=0) self.sqrt_vmax = DoubleVar(widget, value=10000) self.vmax = IntVar(widget, value=10000) self.gamma = DoubleVar(widget, value=0) self.flip = IntVar(widget, value=0) self.mirror = IntVar(widget, value=0) self.white_sky = IntVar(widget, value=0) if input_name: if len(input_name) > 50: split = [ input_name[i:i + 50] for i in range(0, len(input_name), 50) ] input_name = '\n'.join(split) self.fits_name = StringVar(widget, value=input_name) self.fits_name_label = Label(widget, textvar=self.fits_name) # extra widgets control_frame = Frame(widget) self.control_frame = control_frame self.info_label = Label( control_frame, text= 'Scroll up/down to zoom in/out. Click & drag to move the image.') self.mouse_data = StringVar(control_frame, value=' ') self.mouse_data_label = Label(control_frame, textvar=self.mouse_data) self.black_entry = Scale(control_frame, resolution=0.1, variable=self.sqrt_vmin, orient=HORIZONTAL, showvalue=False) self.black_entry.bind("<B1-Motion>", self.contrast) self.black_entry.bind("<ButtonRelease-1>", self.contrast) self.black_entry_label_0 = Label(control_frame, text='Minimum = ', anchor=E) self.black_entry_label = Label(control_frame, textvar=self.vmin, anchor=W) self.black_entry['from_'] = 1 self.black_entry['to'] = 1000 self.white_entry = Scale(control_frame, resolution=0.1, variable=self.sqrt_vmax, orient=HORIZONTAL, showvalue=False) self.white_entry.bind("<B1-Motion>", self.contrast) self.white_entry.bind("<ButtonRelease-1>", self.contrast) self.white_entry_label_0 = Label(control_frame, text='Maximum = ', anchor=E) self.white_entry_label = Label(control_frame, textvar=self.vmax, anchor=W) self.white_entry['from_'] = 1 self.white_entry['to'] = 1000 self.gamma_entry = Scale(control_frame, resolution=0.001, variable=self.gamma, orient=HORIZONTAL, showvalue=False) self.gamma_entry.bind("<B1-Motion>", self.contrast) self.gamma_entry.bind("<ButtonRelease-1>", self.contrast) self.gamma_entry_label_0 = Label(control_frame, text='Stretch factor = ', anchor=E) self.gamma_entry_label = Label(control_frame, textvar=self.gamma, anchor=W) self.gamma_entry['from_'] = 0 self.gamma_entry['to'] = 1 self.flip_button = Checkbutton(control_frame, text='Flip', variable=self.flip, command=self.flip_fov) self.mirror_button = Checkbutton(control_frame, text='Mirror', variable=self.mirror, command=self.mirror_fov) self.reverse_color_button = Checkbutton(control_frame, text='White Sky', variable=self.white_sky, command=self.reverse_color) self.reset_button = Button(control_frame, text='RESET', command=self.reset) self.info_label.grid(row=1, column=1, columnspan=4) self.mouse_data_label.grid(row=2, column=1, columnspan=4) self.black_entry_label_0.grid(row=3, column=1, columnspan=2) self.black_entry_label.grid(row=3, column=3) self.black_entry.grid(row=4, column=1, columnspan=4, sticky=N + S + E + W) self.white_entry_label_0.grid(row=5, column=1, columnspan=2) self.white_entry_label.grid(row=5, column=3) self.white_entry.grid(row=6, column=1, columnspan=4, sticky=N + S + E + W) self.gamma_entry_label_0.grid(row=7, column=1, columnspan=2) self.gamma_entry_label.grid(row=7, column=3) self.gamma_entry.grid(row=8, column=1, columnspan=4, sticky=N + S + E + W) self.reset_button.grid(row=9, column=1) self.flip_button.grid(row=9, column=2) self.mirror_button.grid(row=9, column=3) self.reverse_color_button.grid(row=9, column=4) Label(control_frame, text=' ').grid(row=10, column=1, columnspan=4) self.picked = False if input: self.load_fits(input, input_name, input_options) self.canvas.get_tk_widget().pack(side=TOP) if show_nav: toolbar = NavigationToolbar2Tk(self.canvas, self.widget) toolbar.pack(side=BOTTOM) self.fits_name_label.pack() if show_controls: control_frame.pack() self.canvas.callbacks.connect('scroll_event', self.zoom) self.canvas.callbacks.connect('motion_notify_event', self.move) self.canvas.callbacks.connect('button_press_event', self.pick) self.canvas.callbacks.connect('button_release_event', self.pick) HOPSWidget.__init__(self, window, widget, 'FitsWindow') def load_fits(self, input, input_name=None, input_options=None, draw=True): if isinstance(input, str): fits = get_fits_data(input) input_name = os.path.split(input)[1] elif isinstance(input, pf.ImageHDU) or isinstance( input, pf.PrimaryHDU) or isinstance(input, pf.CompImageHDU): fits = [input] else: raise RuntimeError('Invalid input ', type(input)) if input_name: if len(input_name) > 50: split = [ input_name[i:i + 50] for i in range(0, len(input_name), 50) ] input_name = '\n'.join(split) self.fits_name.set(input_name) self.data = fits[0].data try: self.mean = fits[0].header[self.window.log.mean_key] self.std = fits[0].header[self.window.log.std_key] except: self.mean = np.median(fits[0].data) self.std = plc.mad(fits[0].data) * 1.5 self.black_entry['from_'] = np.sqrt(max(0, np.min(self.data))) self.black_entry['to'] = np.sqrt(np.max(self.data)) self.white_entry['from_'] = np.sqrt(max(0, np.min(self.data))) self.white_entry['to'] = np.sqrt(np.max(self.data)) self.ax.cla() if not self.show_axes: self.ax.axis('off') self.ax.tick_params(axis='y', rotation=90) self.vmin.set( max(1, int(self.mean + self.window.log.frame_low_std * self.std))) self.vmax.set( max(1, int(self.mean + self.window.log.frame_upper_std * self.std))) self.gamma.set(0) if input_options: if input_options[0] != 'auto': self.vmin.set(input_options[0]) if input_options[1] != 'auto': self.vmax.set(input_options[1]) self.gamma.set(input_options[2]) self.flip.set(input_options[3]) self.mirror.set(input_options[4]) self.white_sky.set(input_options[5]) self.sqrt_vmin.set(np.sqrt(self.vmin.get())) self.sqrt_vmax.set(np.sqrt(self.vmax.get())) self.image = self.ax.imshow(self.data**(10**-self.gamma.get()), origin='lower', extent=(0, len(self.data[0]), 0, len(self.data)), cmap=Greys, vmin=self.vmin.get(), vmax=self.vmax.get()) if self.white_sky.get(): self.image.set_cmap(Greys) else: self.image.set_cmap(Greys_r) if self.flip.get(): self.ax.set_ylim(len(self.data) + 5, 0) else: self.ax.set_ylim(0, len(self.data) + 5) if self.mirror.get(): self.ax.set_xlim(len(self.data[0]) + 5, 0) else: self.ax.set_xlim(0, len(self.data[0]) + 5) if draw: self.draw() def reverse_color(self): if self.white_sky.get(): self.image.set_cmap(Greys) else: self.image.set_cmap(Greys_r) self.draw() def flip_fov(self): lims = self.ax.get_ylim() if self.flip.get(): self.ax.set_ylim(max(lims), min(lims)) else: self.ax.set_ylim(min(lims), max(lims)) self.draw() def mirror_fov(self): lims = self.ax.get_xlim() if self.mirror.get(): self.ax.set_xlim(max(lims), min(lims)) else: self.ax.set_xlim(min(lims), max(lims)) self.draw() def contrast(self, event): if self.sqrt_vmin.get() >= self.sqrt_vmax.get(): self.sqrt_vmin.set(self.sqrt_vmax.get() - 1) self.vmin.set(int(self.sqrt_vmin.get()**2)) self.vmax.set(int(self.sqrt_vmax.get()**2)) self.image.set_data(np.maximum(0, self.data)**(10**-self.gamma.get())) self.image.set_clim(self.vmin.get()**(10**-self.gamma.get()), self.vmax.get()**(10**-self.gamma.get())) self.draw() def get_fov_options(self): return [ self.vmin.get(), self.vmax.get(), self.gamma.get(), self.flip.get(), self.mirror.get(), self.white_sky.get() ] def pick(self, event): if isinstance(event, matplotlib.backend_bases.MouseEvent): if event.inaxes is None: pass elif event.name == 'button_press_event': self.picked = (event.xdata, event.ydata) elif event.name == 'button_release_event': self.picked = False def move(self, event): if isinstance(event, matplotlib.backend_bases.MouseEvent): if event.inaxes is None: pass elif event.name == 'motion_notify_event': try: self.mouse_data.set( 'Mouse on: x={0:.2f}, y={1:.2f}, counts={2:.2f}'. format(event.xdata, event.ydata, self.data[int(event.ydata), int(event.xdata)])) except: self.mouse_data.set( 'Mouse on: x={0:.2f}, y={1:.2f}, counts={2}'.format( event.xdata, event.ydata, '-')) if self.picked: dx = event.xdata - self.picked[0] dy = event.ydata - self.picked[1] self.ax.set_xlim(self.ax.get_xlim()[0] - dx, self.ax.get_xlim()[1] - dx) self.ax.set_ylim(self.ax.get_ylim()[0] - dy, self.ax.get_ylim()[1] - dy) self.draw() def zoom(self, event): if isinstance(event, matplotlib.backend_bases.MouseEvent): if event.inaxes is None: pass elif event.name == 'scroll_event': zoom_factor = 1.2 scale_factor = 1.0 if event.button == 'up': scale_factor = 1 / zoom_factor elif event.button == 'down': scale_factor = zoom_factor xdata = event.xdata ydata = event.ydata cur_xlim = self.ax.get_xlim() cur_ylim = self.ax.get_ylim() cur_xrange = (cur_xlim[1] - cur_xlim[0]) cur_yrange = (cur_ylim[1] - cur_ylim[0]) new_xrange = cur_xrange * scale_factor new_yrange = cur_yrange * scale_factor new_xmin = xdata - new_xrange * (xdata - cur_xlim[0]) / cur_xrange new_ymin = ydata - new_yrange * (ydata - cur_ylim[0]) / cur_yrange self.ax.set_xlim([new_xmin, new_xmin + new_xrange]) self.ax.set_ylim([new_ymin, new_ymin + new_yrange]) self.draw() def reset(self): self.ax.set_xlim(0, len(self.data[0]) + 5) self.ax.set_ylim(0, len(self.data) + 5) if self.flip.get(): self.ax.set_ylim(self.ax.get_ylim()[1], self.ax.get_ylim()[0]) if self.mirror.get(): self.ax.set_xlim(self.ax.get_xlim()[1], self.ax.get_xlim()[0]) self.vmin.set( max(1, int(self.mean + self.window.log.frame_low_std * self.std))) self.sqrt_vmin.set(np.sqrt(self.vmin.get())) self.vmax.set( max(1, int(self.mean + self.window.log.frame_upper_std * self.std))) self.sqrt_vmax.set(np.sqrt(self.vmax.get())) self.gamma.set(0) self.image.set_data(np.maximum(0, self.data)**(10**-self.gamma.get())) self.image.set_clim(self.vmin.get()**(10**-self.gamma.get()), self.vmax.get()**(10**-self.gamma.get())) self.draw() def draw(self, update_level=1): self.canvas.draw() if update_level == 0: pass elif update_level == 1: self.window.update_idletasks() elif update_level == 2: self.window.update() def disable(self): for child in self.widget.winfo_children(): try: child.configure(state='disable') except: pass def activate(self): for child in self.widget.winfo_children(): try: child.configure(state='active') except: pass
def create_voices(self): voice_ids = ['1', '2', '3', '4'] SCALES = OrderedDict([ ('pan_pos', {'min': -1, 'max': 1, 'start': 0.5, 'res': 0.001}), ('volume', {'min': 0, 'max': 1, 'start': 0.666, 'res': 0.001}), ('slide_duration_msecs', {'min': 0, 'max': 2000, 'start': 60, 'res': 1}), ('slide_duration_prop', {'min': 0, 'max': 2, 'start': 0.666, 'res': 0.001}), ('binaural_diff', {'min': 0, 'max': 66, 'start': 0.2, 'res': 0.01}) ]) for vid in voice_ids: counter = 0 for sca in SCALES: name = 'voice_' + vid + '_' + sca setattr(self, 'min_' + name, SCALES[sca]['min']) setattr(self, 'max_' + name, SCALES[sca]['max']) this_sca = Scale(self, label=sca, orient=HORIZONTAL, from_=getattr(self, 'min_' + name), to=getattr(self, 'max_' + name), resolution=SCALES[sca]['res']) this_sca.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) this_sca.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) this_sca.grid(column=int(2 + int(vid)), row=counter, sticky=E + W) this_sca.bind("<ButtonRelease>", self.scale_handler) this_sca.ref = name counter += 1 CHECK_BUTTONS = OrderedDict( [('mute', False), ('automate_binaural_diffs', True), ('automate_note_duration_prop', True), ('use_proportional_slide_duration', {'val': True, 'label': 'proportional slide'}), ('automate_pan', True), ('automate_wavetables', True)]) for vid in voice_ids: counter = 0 cb_frame = LabelFrame(self, text="Voice {0} - Automation".format(vid)) setattr(self, 'voice_' + vid + '_cb_frame', cb_frame) for cb in CHECK_BUTTONS: options = CHECK_BUTTONS[cb] name = 'voice_' + vid + '_' + cb if isinstance(options, dict) and 'label' in list(options.keys()): label = options['label'] else: label = cb[9:] if cb[:9] == 'automate_' else cb setattr(self, name, IntVar( value=type(options) == dict and options['val'] or options)) self.this_cb = Checkbutton(cb_frame, text=label, variable=getattr(self, name)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = None self.this_cb.grid(sticky=W, column=0, row=counter) self.this_cb.ref = name counter += 1 # add trigger wavetable-button trigWavetableButton = Button(cb_frame, text='Next Wavetable') trigWavetableButton.bind('<Button-1>', self.trigger_waveform_handler) trigWavetableButton.ref = 'voice_' + vid + "_trigger_wavetable" trigWavetableButton.grid(row=counter) cb_frame.grid(column=int(vid) + 2, row=5, sticky=E + W + N, rowspan=8) for vid in voice_ids: generation_types = ["random", "random_harmonic", "harmonic"] partial_pools = ["even", "odd", "all"] prefix = 'voice_' + vid + '_' types_name = prefix + 'wavetable_generation_type' pools_name = prefix + 'partial_pool' setattr(self, types_name, StringVar()) getattr(self, types_name).set("random") setattr(self, pools_name, StringVar()) getattr(self, pools_name).set("all") target_frame = getattr(self, 'voice_' + vid + '_cb_frame') gen_typ_frame = LabelFrame(target_frame, text="type") gen_typ_frame.grid(row=len(target_frame.winfo_children()), sticky=W) for gen_t in generation_types: gen_t_entry = Radiobutton(gen_typ_frame, value=gen_t, text=gen_t, anchor=W, variable=getattr(self, types_name)) gen_t_entry.bind('<ButtonRelease-1>', self.wt_handler) gen_t_entry.ref = types_name gen_t_entry.grid(row=len(gen_typ_frame.winfo_children()), sticky=W) pp_frame = LabelFrame(target_frame, text="harmonics") for pp in partial_pools: pp_entry = Radiobutton(pp_frame, value=pp, text=pp, anchor=W, variable=getattr(self, pools_name)) pp_entry.bind('<ButtonRelease-1>', self.wt_handler) pp_entry.ref = pools_name pp_entry.grid(row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials = Scale(pp_frame, label='number of harmonics', orient=HORIZONTAL, from_=1, to=24, resolution=1) this_num_partials.ref = prefix + 'num_partials' this_num_partials.grid(column=0, row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials.bind("<ButtonRelease>", self.scale_handler) pp_frame.grid(row=len(target_frame.winfo_children()), sticky=E + W)
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind((host, port)) self.grid() self.columnconfigure(0, minsize=100) self.columnconfigure(1, minsize=200) self.columnconfigure(2, minsize=200) self.columnconfigure(3, minsize=150) self.columnconfigure(4, minsize=150) self.columnconfigure(5, minsize=150) self.columnconfigure(6, minsize=150) self.create_widgets() self.settables = self.assemble_settables() self.gui_logger = logging.getLogger('gui') self.request_update() def create_widgets(self): self.create_monitor() self.create_check_buttons() self.create_ranges() self.create_scales() self.create_radio_buttons() self.create_voices() self.quitButton = Button(self, text='Quit', command=self.quit) self.quitButton.grid(columnspan=7, sticky=E + W) def assemble_settables(self): settables = self.winfo_children() for w in settables: settables += w.winfo_children() return [w for w in settables if w.__class__.__name__ in ['Scale', 'Checkbutton']] def create_radio_buttons(self): # Scale related entries = ['DIATONIC', 'HARMONIC', 'MELODIC', 'PENTATONIC', 'PENTA_MINOR', 'GREEK_CHROMATIC', 'GREEK_ENHARMONIC'] self.scale = StringVar() self.scale.set('DIATONIC') self.rb_frame = Frame(self) for e in entries: rb = Radiobutton(self.rb_frame, value=e, text=e, anchor=W, command=self.send_scale, variable=self.scale) rb.grid(row=len(self.rb_frame.winfo_children()), sticky=W) self.rb_frame.grid(column=1, row=len(self.grid_slaves(column=1)), rowspan=3) def create_monitor(self): self.monitor_frame = LabelFrame(self, text="Monitor and Transport") this_cycle = Scale(self.monitor_frame, label='cycle_pos', orient=HORIZONTAL, from_=1, to=16, resolution=1) this_cycle.disable, this_cycle.enable = (None, None) this_cycle.ref = 'cycle_pos' this_cycle.grid(column=0, row=0, sticky=E + W) self.updateButton = Button(self.monitor_frame, text='Reload all Settings', command=self.request_update) self.updateButton.grid(row=1, sticky=E + W) self.ForceCaesuraButton = Button(self.monitor_frame, text='Force Caesura', command=self.force_caesura) self.ForceCaesuraButton.grid(row=2, sticky=E + W) self.saveBehaviourButton = Button(self.monitor_frame, text='Save current behaviour', command=self.request_saving_behaviour) self.saveBehaviourButton.grid(row=3, sticky=E + W) self.saveBehaviourNameEntry = Entry(self.monitor_frame) self.saveBehaviourNameEntry.grid(row=4, sticky=E + W) self.saveBehaviourNameEntry.bind('<KeyRelease>', self.request_saving_behaviour) self.selected_behaviour = StringVar() self.selected_behaviour.trace('w', self.new_behaviour_chosen) self.savedBehavioursMenu = OptionMenu(self.monitor_frame, self.selected_behaviour, None,) self.savedBehavioursMenu.grid(row=5, sticky=E + W) self.monitor_frame.grid(column=0, row=10, sticky=E + W) def request_update(self): self.send({'sys': 'update'}) def request_saving_behaviour(self, event=None): """callback for save behaviour button and textentry""" if event and event.widget == self.saveBehaviourNameEntry: if event.keysym == 'Return': name = self.saveBehaviourNameEntry.get() self.saveBehaviourNameEntry.delete(0, len(name)) else: return else: # button was pressed name = self.saveBehaviourNameEntry.get() if name: self.send({'sys': ['save_behaviour', name]}) def force_caesura(self): self.send({'force_caesura': True}) def create_voices(self): voice_ids = ['1', '2', '3', '4'] SCALES = OrderedDict([ ('pan_pos', {'min': -1, 'max': 1, 'start': 0.5, 'res': 0.001}), ('volume', {'min': 0, 'max': 1, 'start': 0.666, 'res': 0.001}), ('slide_duration_msecs', {'min': 0, 'max': 2000, 'start': 60, 'res': 1}), ('slide_duration_prop', {'min': 0, 'max': 2, 'start': 0.666, 'res': 0.001}), ('binaural_diff', {'min': 0, 'max': 66, 'start': 0.2, 'res': 0.01}) ]) for vid in voice_ids: counter = 0 for sca in SCALES: name = 'voice_' + vid + '_' + sca setattr(self, 'min_' + name, SCALES[sca]['min']) setattr(self, 'max_' + name, SCALES[sca]['max']) this_sca = Scale(self, label=sca, orient=HORIZONTAL, from_=getattr(self, 'min_' + name), to=getattr(self, 'max_' + name), resolution=SCALES[sca]['res']) this_sca.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) this_sca.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) this_sca.grid(column=int(2 + int(vid)), row=counter, sticky=E + W) this_sca.bind("<ButtonRelease>", self.scale_handler) this_sca.ref = name counter += 1 CHECK_BUTTONS = OrderedDict( [('mute', False), ('automate_binaural_diffs', True), ('automate_note_duration_prop', True), ('use_proportional_slide_duration', {'val': True, 'label': 'proportional slide'}), ('automate_pan', True), ('automate_wavetables', True)]) for vid in voice_ids: counter = 0 cb_frame = LabelFrame(self, text="Voice {0} - Automation".format(vid)) setattr(self, 'voice_' + vid + '_cb_frame', cb_frame) for cb in CHECK_BUTTONS: options = CHECK_BUTTONS[cb] name = 'voice_' + vid + '_' + cb if isinstance(options, dict) and 'label' in list(options.keys()): label = options['label'] else: label = cb[9:] if cb[:9] == 'automate_' else cb setattr(self, name, IntVar( value=type(options) == dict and options['val'] or options)) self.this_cb = Checkbutton(cb_frame, text=label, variable=getattr(self, name)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = None self.this_cb.grid(sticky=W, column=0, row=counter) self.this_cb.ref = name counter += 1 # add trigger wavetable-button trigWavetableButton = Button(cb_frame, text='Next Wavetable') trigWavetableButton.bind('<Button-1>', self.trigger_waveform_handler) trigWavetableButton.ref = 'voice_' + vid + "_trigger_wavetable" trigWavetableButton.grid(row=counter) cb_frame.grid(column=int(vid) + 2, row=5, sticky=E + W + N, rowspan=8) for vid in voice_ids: generation_types = ["random", "random_harmonic", "harmonic"] partial_pools = ["even", "odd", "all"] prefix = 'voice_' + vid + '_' types_name = prefix + 'wavetable_generation_type' pools_name = prefix + 'partial_pool' setattr(self, types_name, StringVar()) getattr(self, types_name).set("random") setattr(self, pools_name, StringVar()) getattr(self, pools_name).set("all") target_frame = getattr(self, 'voice_' + vid + '_cb_frame') gen_typ_frame = LabelFrame(target_frame, text="type") gen_typ_frame.grid(row=len(target_frame.winfo_children()), sticky=W) for gen_t in generation_types: gen_t_entry = Radiobutton(gen_typ_frame, value=gen_t, text=gen_t, anchor=W, variable=getattr(self, types_name)) gen_t_entry.bind('<ButtonRelease-1>', self.wt_handler) gen_t_entry.ref = types_name gen_t_entry.grid(row=len(gen_typ_frame.winfo_children()), sticky=W) pp_frame = LabelFrame(target_frame, text="harmonics") for pp in partial_pools: pp_entry = Radiobutton(pp_frame, value=pp, text=pp, anchor=W, variable=getattr(self, pools_name)) pp_entry.bind('<ButtonRelease-1>', self.wt_handler) pp_entry.ref = pools_name pp_entry.grid(row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials = Scale(pp_frame, label='number of harmonics', orient=HORIZONTAL, from_=1, to=24, resolution=1) this_num_partials.ref = prefix + 'num_partials' this_num_partials.grid(column=0, row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials.bind("<ButtonRelease>", self.scale_handler) pp_frame.grid(row=len(target_frame.winfo_children()), sticky=E + W) def wt_handler(self, event): print(event.widget.tk) ref = event.widget.ref self.send({ref: getattr(self, ref).get()}) def create_check_buttons(self): self.cb_frame = LabelFrame(self, text="Global Settings") for cb in CHECK_BUTTONS: label = cb target_parent = self.cb_frame if isinstance(CHECK_BUTTONS[cb], dict) and 'sub_frame' in list(CHECK_BUTTONS[cb].keys()): target_parent = getattr(self, CHECK_BUTTONS[cb]['sub_frame']) setattr(self, cb, IntVar(value=type(CHECK_BUTTONS[cb]) == dict and CHECK_BUTTONS[cb]['val'] or CHECK_BUTTONS[cb])) self.this_cb = Checkbutton(target_parent, text=label, variable=getattr(self, cb)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = (type(CHECK_BUTTONS[cb]) == dict and 'disable' in list(CHECK_BUTTONS[cb].keys())) self.this_cb.grid(sticky=W, column=0, row=len(target_parent.winfo_children())) self.this_cb.ref = cb for but in GLOBAL_BUTTONS: label = but ele = GLOBAL_BUTTONS[but] this_but = Button(self.cb_frame, text=but) this_but.bind('<ButtonRelease-1>', getattr(self, ele['handler'])) this_but.ref = but this_but.grid(sticky=W, column=0, row=len(self.cb_frame.winfo_children())) self.cb_frame.grid(column=0, row=0, rowspan=10, sticky=N) def new_behaviour_chosen(self, a, b, c): self.send({'sys': ['change_behaviour', self.selected_behaviour.get()]}) def set_value(self, name, val): '''sets a widget to the specified value various different widget types need custom setting functionality''' direct = ['scale', 'wavetable_generation_type', 'partial_pool'] if [x for x in direct if match("(voice_\d_|)" + x, name)]: self.gui_logger.info("setting: '{0}' to '{1}' in GUI".format(name, val)) getattr(self, name).set(val) return if name == 'saved_behaviours' and len(val): self.savedBehavioursMenu.destroy() self.savedBehavioursMenu = OptionMenu(self.monitor_frame, self.selected_behaviour, *sorted(val)) self.savedBehavioursMenu.grid(row=5, sticky=E + W) return for w in self.settables: typ = w.__class__.__name__ if w.ref == name: # print "setting '{0}' of type: '{1}' to: {2}".format(name, typ, val) if typ == 'Scale': w.set(val) elif typ == "Checkbutton": w.select() if val else w.deselect() def check_boxes_handler(self, event): '''handles checkbox events. shows and hides gui elements according to their enable/disable fields''' # print event.__dict__ # print event.widget.__dict__ ref = event.widget.ref val = not getattr(self, ref).get() # because is read before the var is changed self.send({ref: val}) # print ref, val # handle gui elements # enable/disable functionality temporarily(?) commented on: # Wed Aug 17 09:39:54 CEST 2011 # if event.widget.disable: # for w in self.children.values(): # # # this try clause is for debugging, remove when stable # try: # w.ref # #print w.ref # except: # pass # if (w.__class__.__name__ == 'Scale' and # (w.disable or w.enable)): # if w.disable == ref: # if val: # w.grid() # else: # w.grid_remove() # elif w.enable == ref: # if val: # w.grid_remove() # else: # w.grid() # #print w.disable, w.enable def create_scales(self): counter = 0 for sca in SCALES: label = SCALES[sca]['label'] if 'label' in list(SCALES[sca].keys()) else sca setattr(self, 'min_' + sca, SCALES[sca]['min']) setattr(self, 'max_' + sca, SCALES[sca]['max']) self.this_scale = Scale(self, label=label, orient=HORIZONTAL, from_=getattr(self, 'min_' + sca), to=getattr(self, 'max_' + sca), resolution=SCALES[sca]['res']) self.this_scale.set(SCALES[sca]['start']) self.this_scale.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) self.this_scale.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) if 'pos' in list(SCALES[sca].keys()): pos = SCALES[sca]['pos'] col = pos['c'] row = pos['r'] else: row = counter col = 1 counter += 1 self.this_scale.grid(column=col, row=row, sticky=E + W) self.this_scale.ref = sca self.this_scale.bind("<ButtonRelease>", self.scale_handler) def scale_handler(self, event): self.send({event.widget.ref: event.widget.get()}) self.gui_logger.info("handling scale: {0}, with new value: {1}".format( event.widget.ref, event.widget.get())) def trigger_waveform_handler(self, event): self.send({event.widget.ref: True}) # print event.widget.ref, "- triggering wavetable" def send_scale(self): do = {'scale': self.scale.get()} self.send(do) def send(self, msg): self.gui_logger.info("sending: {0}".format(msg)) self.send_sock.sendto(json.dumps(msg), (remote_host, send_port)) def create_ranges(self): counter = 0 for ran in RANGES: setattr(self, 'min_' + ran, RANGES[ran]['min']) setattr(self, 'max_' + ran, RANGES[ran]['max']) self.this_min_scale = Scale(self, label='min ' + ran, orient=HORIZONTAL, from_=getattr(self, 'min_' + ran), to=getattr(self, 'max_' + ran), resolution=RANGES[ran]['res']) self.this_max_scale = Scale(self, label='max ' + ran, orient=HORIZONTAL, from_=getattr(self, 'min_' + ran), to=getattr(self, 'max_' + ran), resolution=RANGES[ran]['res']) self.this_min_scale.set(RANGES[ran]['min_start']) self.this_max_scale.set(RANGES[ran]['max_start']) self.this_min_scale.enable = ('enable' in list(RANGES[ran].keys()) and RANGES[ran]['enable'] or None) self.this_min_scale.disable = ('disable' in list(RANGES[ran].keys()) and RANGES[ran]['disable'] or None) self.this_max_scale.enable = ('enable' in list(RANGES[ran].keys()) and RANGES[ran]['enable'] or None) self.this_max_scale.disable = ('disable' in list(RANGES[ran].keys()) and RANGES[ran]['disable'] or None) self.this_min_scale.grid(column=2, row=counter, sticky=E + W) self.this_max_scale.grid(column=2, row=counter + 1, sticky=E + W) self.this_min_scale.ref = 'min_' + ran self.this_max_scale.ref = 'max_' + ran self.this_min_scale.bind("<ButtonRelease>", self.scale_handler) self.this_max_scale.bind("<ButtonRelease>", self.scale_handler) counter += 2 def socket_read_handler(self, file, mask): data_object = json.loads(file.recv(1024)) do = list(data_object.items())[0] self.set_value(do[0], do[1])
def __init__(self,parent,base_fl,lecteur): self.police_titre=('Times', -20, 'bold') self.police_nombre=('Arial', -20, 'bold') self.parent=parent self.bfl=base_fl self.lecteur=lecteur self.mot1="" self.mot2="" self.titre_colonne1=Label(parent,text="Base de données",font=self.police_titre) self.titre_colonne1.grid(column=0,row=0) self.titre_colonne2=Entry(parent,width=15,font=self.police_titre) self.titre_colonne2.grid(column=1,row=0) self.titre_colonne2.insert(END,self.mot1) self.titre_colonne3=Entry(parent,width=15,font=self.police_titre) self.titre_colonne3.grid(column=2,row=0) self.titre_colonne3.insert(END,self.mot2) self.titre_colonne3.bind("<Return>",self.actualise_mot2) self.titre_colonne4=Label(parent,text="Poids de chaque base",font=self.police_titre) self.titre_colonne4.grid(column=3,row=0) self.titre_ligne=[] for k in range(self.bfl.n_base): tl=Label(parent,font=self.police_titre,text=self.bfl.bddl_brute[k].nom) tl.grid(column=0,row=k+1) tl.bind("<Enter>", lambda event, obj=self.bfl.bddl_brute[k]: self.actualise_info(event, obj)) self.titre_ligne.append(tl) self.titre_derniere_ligne=Label(parent,font=self.police_titre,text="Cumul:") self.titre_derniere_ligne.grid(column=0,row=k+2) self.curseur=[] def enter(event,c): c.active=True def leave(event,c): c.active=False for k in range(self.bfl.n_base): c=Scale(parent, orient='horizontal', resolution=1/10**NB_DECIMALES,from_=0, to=1, command=self.actualise_cumul) c.grid(column=3,row=k+1) #Remettre cette ligne pour une répartition équitable des lectures #c.set(1.0/self.bfl.n_base) #A CHANGER: valeurs initales des poids de chaque base dict_params={"Blog":0.21,"Twitter":0.21,"Journaux":0.04,"Livres":0.12,"Films":0.42} c.set(dict_params[self.bfl.bddl_brute[k].nom]) c.val_mem=c.get() c.active=False c.bind("<Enter>", lambda event, obj=c: enter(event, obj)) c.bind("<Leave>", lambda event, obj=c: leave(event, obj)) self.curseur.append(c) self.cumul=Label(parent,font=self.police_nombre) self.cumul.grid(column=3,row=k+2) self.freqp1=Label(parent,font=self.police_nombre) self.freqp1.grid(column=1,row=k+2) self.freqp2=Label(parent,font=self.police_nombre) self.freqp2.grid(column=2,row=k+2) self.freq1=[] for k in range(self.bfl.n_base): f=Label(parent,font=self.police_nombre,text="#") f.grid(column=1,row=k+1) self.freq1.append(f) self.freq2=[] for k in range(self.bfl.n_base): f=Label(parent,font=self.police_nombre,text="#") f.grid(column=2,row=k+1) self.freq2.append(f) self.modifie_mot1("") self.modifie_mot2("")