class ConfigWindow(Toplevel): '''Represent the configuration window.''' def __init__(self, parent=None): '''Constructor of ConfigWindow.''' Toplevel.__init__(self, parent) self.title('Configuracion') self._states = [IntVar(value=CONFIG['GAME_TRACKING']), IntVar(value=CONFIG['CONFIRM_EXIT'])] self._cbox_gtrack = Checkbutton(self, text='Seguimiento del juego') self._cbox_gtrack.config(variable=self._states[0]) self._cbox_confexit = Checkbutton(self, text='Confirmacion al salir') self._cbox_confexit.config(variable=self._states[1]) self._cbox_gtrack.grid(row=0, column=0, sticky=W) self._cbox_confexit.grid(row=1, column=0, sticky=W) self._button_cancel = Button(self, text='Cancelar', command=self.destroy) self._button_cancel.grid(row=3, column=1, sticky=E) self._button_accept = Button(self, text='Guardar y Salir') self._button_accept.config(command=self.save_config) self._button_accept.grid(row=3, column=0, sticky=E) def save_config(self): pass def get_state_game_tracking(self): return self._states[0].get() def get_state_confirm_exit(self): return self._states[1].get()
class ConfigWindow(Toplevel): '''Represent the configuration window.''' def __init__(self, parent=None): '''Constructor of ConfigWindow.''' Toplevel.__init__(self, parent) self.title('Configuracion') self._states = [ IntVar(value=CONFIG['GAME_TRACKING']), IntVar(value=CONFIG['CONFIRM_EXIT']) ] self._cbox_gtrack = Checkbutton(self, text='Seguimiento del juego') self._cbox_gtrack.config(variable=self._states[0]) self._cbox_confexit = Checkbutton(self, text='Confirmacion al salir') self._cbox_confexit.config(variable=self._states[1]) self._cbox_gtrack.grid(row=0, column=0, sticky=W) self._cbox_confexit.grid(row=1, column=0, sticky=W) self._button_cancel = Button(self, text='Cancelar', command=self.destroy) self._button_cancel.grid(row=3, column=1, sticky=E) self._button_accept = Button(self, text='Guardar y Salir') self._button_accept.config(command=self.save_config) self._button_accept.grid(row=3, column=0, sticky=E) def save_config(self): pass def get_state_game_tracking(self): return self._states[0].get() def get_state_confirm_exit(self): return self._states[1].get()
class ChecklistItem: def __init__(self, master, task): self.task = task # Allows the Checkbutton value to be dynamic self.value = StringVar() self.value.set("Imcomplete") self.item = Checkbutton(master, text=self.task) self.item.config(variable=self.value, onvalue="Complete", offvalue="Imcomplete")
class CheckBox: def __init__(self, master, value, title=None): self.value = BooleanVar() self.value.set(value) self.title = title self.cb = Checkbutton(master, variable=self.value, onvalue=1, offvalue=0) if title is not None: self.cb.config(text=title)
def __init__(self, master, title, x_coor, y_coor, serial=False, p_value_x_coor=365, p_value_width=500, result_x_coor=870, result_width=350, font_size=12, two_columns=False): self.__chb_var = IntVar() self.__p_value = StringVar() self.__result = StringVar() self.__p_value_02 = StringVar() self.__result_02 = StringVar() checkbox = Checkbutton(master, text=title, variable=self.__chb_var) checkbox.config(font=("Calibri", font_size)) checkbox.place(x=x_coor, y=y_coor) p_value_entry = Entry(master, textvariable=self.__p_value) p_value_entry.config(state=DISABLED) p_value_entry.place(x=p_value_x_coor, y=y_coor, width=p_value_width, height=25) result_entry = Entry(master, textvariable=self.__result) result_entry.config(state=DISABLED) result_entry.place(x=result_x_coor, y=y_coor, width=result_width, height=25) if serial and two_columns: p_value_entry_02 = Entry(master, textvariable=self.__p_value_02) p_value_entry_02.config(state=DISABLED) p_value_entry_02.place(x=875, y=y_coor, width=235, height=25) result_entry_02 = Entry(master, textvariable=self.__result_02) result_entry_02.config(state=DISABLED) result_entry_02.place(x=1115, y=y_coor, width=110, height=25) elif serial and not two_columns: p_value_entry_02 = Entry(master, textvariable=self.__p_value_02) p_value_entry_02.config(state=DISABLED) p_value_entry_02.place(x=365, y=y_coor + 25, width=500, height=25) result_entry_02 = Entry(master, textvariable=self.__result_02) result_entry_02.config(state=DISABLED) result_entry_02.place(x=870, y=y_coor + 25, width=350, height=25)
def Checkbox(root, style="", **options): props = { 'activeforeground': load_color(style)['color'], 'activebackground': load_color(style)['acColor'] } props.update(**options) C = Checkbutton(root) C.config(props) C.pack()
class CheckRaddioButtons: def __init__(self, master): self.master = master master.title("Presenting choices with check buttons and radio buttons") # Create a checkbutton and show in window self.checkbutton = Checkbutton(master, text='SPAN? ', font=('Arial', 12, 'bold')) self.checkbutton.pack() self.spam = StringVar() self.spam.set('SPAM!') self.spam.get() self.checkbutton.config(text="Span", variable=self.spam, onvalue="Span Please", offvalue="Boo Span") print(self.spam.get()) print(self.spam.get()) self.breakfast = StringVar() self.radiobutton = Radiobutton(root, text="SPAM", variable=self.breakfast) self.radiobutton.pack() self.rbeggs = Radiobutton(root, text="Eggs", variable=self.breakfast, value='Eggs') self.rbeggs.pack() self.rbsausage = Radiobutton(root, text="Sausage", variable=self.breakfast, value='Sausage') self.rbsausage.pack() self.rbspan = Radiobutton(root, text="SPAM", variable=self.breakfast, value='SPAM') self.rbspan.pack() self.breakfast.get() self.checkbutton.config(variable=self.breakfast)
def _display_fields(self): for i in range(6): current_field = NewPlayerField(self) is_active = Checkbutton(self, takefocus=0, variable=current_field.active) if i == 0: current_field.active.set(1) is_active.config(state=DISABLED) is_active.grid(row=i % 6, column=0, padx=5, pady=5, sticky=E) current_field.grid(row=i % 6, column=1, sticky=W) self.player_setups.append(current_field) start_button = Button( self, textvariable=self.master.ui_text_variables['start_button'], command=self.player_setup_done) start_button.grid(row=0, column=2, rowspan=6, sticky=W)
class GuiInterface(object): def __init__(self): self.title = "Movement Sense" # self.path = "C:\\Age_Estimation_Project\\bag_files\\sub005\\left\\" # self.path = 'C:/Users/markf/Downloads/Project/sub003/Squat/' self.path = '' self.root = None self.combo = None self.instructionsWindow = None self.aboutWindow = None self.textBox = None self.buttonRun = None self.buttonLog = None self.buttonBrowse = None self.checkButtonKnees = None self.checkButtonMass = None self.checkButtonKyphosis = None self.checkButtonFront = None self.checkButtonSide = None self.checkButtonBack = None self.kneesCheckBox = None self.massCheckBox = None self.KyphosisCheckBox = None self.frontCheckBox = None self.sideCheckBox = None self.backCheckBox = None self.orientations = [] self.calculations = [] self.cameraOrientations = ['0', '90 right', '180', '90 left'] self.frontOrientation = None self.sideOrientation = None self.backOrientation = None def setupInterface(self): # initialize windows self.root = Tk() self.root.title(self.title) self.root.configure(bd=10) # self.root.geometry("300x200") # Column 0 # Calculation checkboxes: Label(self.root, text="Calculation").grid(row=0, column=0, sticky=W, pady=5) # add kyphosis button self.KyphosisCheckBox = BooleanVar() self.KyphosisCheckBox.set(False) self.checkButtonKyphosis = Checkbutton(self.root, text="Kyphosis", variable=self.KyphosisCheckBox, command=lambda: self.addToCalculations('Kyphosis'), cursor="hand2") self.checkButtonKyphosis.grid(row=1, column=0, sticky=W) # add mass center button self.massCheckBox = BooleanVar() self.massCheckBox.set(False) self.checkButtonMass = Checkbutton(self.root, text="Mass Center", variable=self.massCheckBox, command=lambda: self.addToCalculations('Mass'), cursor="hand2") self.checkButtonMass.grid(row=2, column=0, sticky=W) # add knees button self.kneesCheckBox = BooleanVar() self.kneesCheckBox.set(False) self.checkButtonKnees = Checkbutton(self.root, text="Knees", variable=self.kneesCheckBox, command=lambda: self.addToCalculations('Knees'), cursor="hand2") self.checkButtonKnees.grid(row=3, column=0, sticky=W) # Column 1 # separator line separator = ttk.Separator(self.root, orient='vertical') separator.grid(row=0, column=1, rowspan=4, sticky="ns", padx=5) # Column 2 # Orientation checkboxes: Label(self.root, text="Orientation").grid(row=0, column=2, sticky=W + E, pady=5) # add front camera button self.frontCheckBox = BooleanVar() self.frontCheckBox.set(False) self.checkButtonFront = Checkbutton(self.root, text="Front", variable=self.frontCheckBox, command=lambda: self.addToOrientation('Front'), cursor="hand2") self.checkButtonFront.grid(row=1, column=2, sticky=W) # add side camera button self.sideCheckBox = BooleanVar() self.sideCheckBox.set(False) self.checkButtonSide = Checkbutton(self.root, text="Side", variable=self.sideCheckBox, command=lambda: self.addToOrientation('Side'), cursor="hand2") self.checkButtonSide.grid(row=2, column=2, sticky=W) # add back camera button self.backCheckBox = BooleanVar() self.backCheckBox.set(False) self.checkButtonBack = Checkbutton(self.root, text="Back", variable=self.backCheckBox, command=lambda: self.addToOrientation('Back'), cursor="hand2") self.checkButtonBack.grid(row=3, column=2, sticky=W) # Column 3 Label(self.root, text="Camera Angle").grid(row=0, column=3, sticky=W + E, pady=5, padx=10) self.frontOrientation = ttk.Combobox(self.root, width=5, values=self.cameraOrientations) self.frontOrientation.current(1) self.frontOrientation.grid(row=1, column=3, sticky=W, padx=10) self.sideOrientation = ttk.Combobox(self.root, width=5, values=self.cameraOrientations) self.sideOrientation.current(1) self.sideOrientation.grid(row=2, column=3, sticky=W, padx=10) self.backOrientation = ttk.Combobox(self.root, width=5, values=self.cameraOrientations) self.backOrientation.current(1) self.backOrientation.grid(row=3, column=3, sticky=W, padx=10) # add choose file button self.buttonBrowse = Button(self.root, text="Vicon Path", width=12, command=lambda: self.browseFile(), cursor="hand2", activebackground="Lavender") self.buttonBrowse.grid(row=4, column=0, sticky=W + E, pady=10) # add generate log button self.buttonLog = Button(self.root, text="Generate logs", width=12, command=lambda: self.startMainThread(self.GenerateLogs), cursor="hand2", activebackground="Lavender") self.buttonLog.grid(row=4, column=2, sticky=W + E, pady=10) # add run button self.buttonRun = Button(self.root, text="Run", command=lambda: self.startMainThread(self.runButton), cursor="hand2", activebackground="Lavender", width=10) self.buttonRun.grid(row=4, column=3, pady=10) # add toolbar menubar = Menu(self.root, tearoff=0) self.root.config(menu=menubar) menubar.add_command(label='Instructions', command=lambda: self.openInstructionsWindow()) menubar.add_command(label='Reset', command=lambda: self.resetPickle()) menubar.add_command(label='About', command=lambda: self.openAboutWindow()) # add text box self.textBox = StringVar() self.textBox.set("Welcome") Label(self.root, textvariable=self.textBox).grid(row=5, column=0, sticky=W + E, columnspan=4) self.root.protocol("WM_DELETE_WINDOW", self.on_closing) self.root.mainloop() def on_closing(self): if messagebox.askokcancel("Quit", "Do you want to quit?"): self.root.destroy() def resetPickle(self): path = self.path + 'loadfiles/' if os.path.isdir(path): files = glob.glob(path + '*') if len(files) > 0: if messagebox.askokcancel("Yes", "Delete all cached files?"): for f in files: os.remove(f) self.textBox.set("Cache cleared") else: self.textBox.set("Cache is already clear") else: self.textBox.set("No cache folder in here") def openInstructionsWindow(self): if self.instructionsWindow is None: self.instructionsWindow = Toplevel(self.root) self.instructionsWindow.title("Instructions") self.instructionsWindow.geometry("710x460") Label(self.instructionsWindow, text=INSTRUCTIONS, justify='left').pack() self.instructionsWindow.protocol("WM_DELETE_WINDOW", self.onInstructionsClose) def openAboutWindow(self): if self.aboutWindow is None: self.aboutWindow = Toplevel(self.root) self.aboutWindow.title("About") self.aboutWindow.geometry("50x100") Label(self.aboutWindow, text="Noy Boutbul\nMark Fesenko").pack() self.aboutWindow.protocol("WM_DELETE_WINDOW", self.onAboutClose) def onInstructionsClose(self): self.instructionsWindow.destroy() self.instructionsWindow = None def onAboutClose(self): self.aboutWindow.destroy() self.aboutWindow = None def runButton(self): if len(self.orientations) == 0: self.textBox.set("Please choose camera orientation settings") elif len(self.calculations) == 0: self.textBox.set("Please choose measurements") elif not os.path.isfile(self.path + 'vicon.csv'): self.textBox.set("Please select a valid path") else: self.textBox.set("Working...") self.disableButtons() self.Main() self.textBox.set("Done!") self.enableButtons() def disableButtons(self): self.buttonRun.configure(state='disabled') # must be active, disabled, or normal self.buttonLog.configure(state='disabled') self.buttonBrowse.configure(state='disabled') self.checkButtonFront.config(state='disabled') self.checkButtonSide.config(state='disabled') self.checkButtonBack.config(state='disabled') self.checkButtonKyphosis.config(state='disabled') self.checkButtonKnees.config(state='disabled') self.checkButtonMass.config(state='disabled') self.frontOrientation.config(state='disabled') self.sideOrientation.config(state='disabled') self.backOrientation.config(state='disabled') def enableButtons(self): self.buttonRun.configure(state='normal') # must be active, disabled, or normal self.buttonLog.configure(state='normal') self.buttonBrowse.configure(state='normal') self.checkButtonFront.config(state='normal') self.checkButtonSide.config(state='normal') self.checkButtonBack.config(state='normal') self.checkButtonKyphosis.config(state='normal') self.checkButtonKnees.config(state='normal') self.checkButtonMass.config(state='normal') self.frontOrientation.config(state='normal') self.sideOrientation.config(state='normal') self.backOrientation.config(state='normal') def startMainThread(self, button): global funcThread funcThread = threading.Thread(target=button) funcThread.start() def browseFile(self): file = filedialog.askopenfile(parent=self.root, mode='rb', title='Choose a file') try: self.path = file.name.replace('vicon.csv', '') except: self.textBox.set("Please select a valid path") def translateAngle(self, camera): angle = self.cameraOrientations.index(camera.get()) return 360 - (90 * angle) def checkPickleFiles(self): for filename in ['orientations', 'angles', 'openposeSkeletonsLists', 'openposeTimestampsLists']: if not os.path.isfile(self.path + 'loadfiles/' + filename): return False return True def addToCalculations(self, param): if param in self.calculations: self.calculations.remove(param) return self.calculations.append(param) self.calculations = sorted(self.calculations) def addToOrientation(self, param): if param in self.orientations: self.orientations.remove(param) return self.orientations.append(param) self.orientations = sorted(self.orientations) def getRotationAngle(self, orientation): name = orientation.lower() + 'Orientation' attr = getattr(self, name) rotationAngle = self.translateAngle(attr) return rotationAngle def GenerateLogs(self): if len(self.orientations) == 0: self.textBox.set("Please choose orientations") return else: self.disableButtons() for i in range(len(self.orientations)): self.textBox.set("Generating " + self.orientations[i] + " orientation log files...") rotationAngle = self.getRotationAngle(self.orientations[i]) try: GenerateLog(self.path, self.orientations[i], rotationAngle) except: self.textBox.set("Path error. Please choose correct path") self.disableButtons() return if len(self.orientations) > 0: self.textBox.set("Done generating log files!") self.enableButtons() def Main(self): openposeSkeletonsLists = [] openposeTimestampsLists = [] # List of vicon skeletons viconSkeletons = ViconReader(self.path + 'vicon.csv') viconSkeletons = SyncByMovementVicon(viconSkeletons) picklePath = self.path + 'loadfiles\\' pathlib.Path(picklePath).mkdir(parents=True, exist_ok=True) if os.path.exists(self.path + 'loadfiles'): self.textBox.set("Loading cached files...") angles = [self.translateAngle(self.frontOrientation), self.translateAngle(self.sideOrientation), self.translateAngle(self.backOrientation)] pickleOrientations = None pickleAngles = None if self.checkPickleFiles(): pickleOrientations = pickle.load(open(self.path + 'loadfiles\\' + "orientations", 'rb')) pickleAngles = pickle.load(open(self.path + 'loadfiles\\' + "angles", 'rb')) openposeSkeletonsLists = pickle.load(open(self.path + 'loadfiles\\' + "openposeSkeletonsLists", 'rb')) openposeTimestampsLists = pickle.load(open(self.path + 'loadfiles\\' + "openposeTimestampsLists", 'rb')) if self.orientations != pickleOrientations or angles != pickleAngles: # Two lists: one of Openpose skeletons, one of timestamps for i in range(len(self.orientations)): self.textBox.set("Working on " + str(i + 1) + '/' + str(len(self.orientations)) + " bag file") rotationAngle = self.getRotationAngle(self.orientations[i]) openposeSkeletons, openposeTimestamps = BagFileSetup(self.path, self.orientations[i], rotationAngle) openposeSkeletons, openposeTimestamps = SyncByMovementOpenpose(openposeSkeletons, openposeTimestamps) openposeSkeletonsLists.append(openposeSkeletons) openposeTimestampsLists.append(openposeTimestamps) dirPath = self.path + 'loadfiles' try: os.mkdir(dirPath) except OSError: pass pickle.dump(angles, open(self.path + 'loadfiles\\' + "angles", 'wb')) pickle.dump(self.orientations, open(self.path + 'loadfiles\\' + "orientations", 'wb')) pickle.dump(openposeSkeletonsLists, open(self.path + 'loadfiles\\' + "openposeSkeletonsLists", 'wb')) pickle.dump(openposeTimestampsLists, open(self.path + 'loadfiles\\' + "openposeTimestampsLists", 'wb')) self.textBox.set("Calculating measurements...") openposeMeasurementsMat = [] viconMeasurementsMat = [] for i in range(len(self.calculations)): openposeMeasurements = [] viconMeasurements = [] for j in range(len(self.orientations)): openposeData, correspondingTimestamps = CalculateMeasurement(openposeSkeletonsLists[j], self.calculations[i], openposeTimestampsLists[j]) viconData = CalculateMeasurement(viconSkeletons, self.calculations[i]) cutViconData = matchTimestamps(openposeTimestampsLists[j], viconData) cutViconData, openposeData, correspondingTimestamps = removeOutliers(cutViconData, openposeData, correspondingTimestamps) viconMeasurements.append(cutViconData) openposeMeasurements.append([openposeData, correspondingTimestamps]) openposeMeasurementsMat.append(openposeMeasurements) viconMeasurementsMat.append(viconMeasurements) self.textBox.set("Exporting graphs...") graphsOutput = self.path + 'Graphs\\' excelOutput = self.path + 'Excel\\' pathlib.Path(graphsOutput).mkdir(parents=True, exist_ok=True) pathlib.Path(excelOutput).mkdir(parents=True, exist_ok=True) for i in range(len(self.calculations)): for j in range(len(self.orientations)): GenerateExcel(openposeMeasurementsMat[i][j][1], openposeMeasurementsMat[i][j][0], viconMeasurementsMat[i][j], excelOutput, self.calculations[i] + '_' + self.orientations[j]) GenerateGraph(openposeMeasurementsMat[i][j][1], openposeMeasurementsMat[i][j][0], viconMeasurementsMat[i][j], self.calculations[i], self.orientations[j], graphsOutput) GenerateGraphOfCorrelation(openposeMeasurementsMat[i][j][0], viconMeasurementsMat[i][j], self.calculations[i] + '_' + self.orientations[j], graphsOutput)
class ControlAnnouncement: def __init__(self, parent): self.announcement = Announcement( sorted(list(users.keys()))[0], sorted(list(mail.keys()))[0]) self.initializeGui(parent) def initializeGui(self, parent): self.parent = parent self.frame = Frame(self.parent) self.frame.grid(column=0, row=0) Label(self.frame, text="User").grid(row=0, sticky=W) Label(self.frame, text="Type").grid(row=1, sticky=W) userList = sorted(list(users.keys())) self.comboBoxUser = Combobox(self.frame, state="readonly", width=20, values=userList) self.comboBoxUser.set(userList[0]) self.comboBoxUser.grid(row=0, column=1, sticky=W) self.comboBoxUser.bind('<<ComboboxSelected>>', self.updateUser) announcementTypes = sorted(list(mail.keys())) self.comboBoxType = Combobox(self.frame, state="readonly", width=35, values=announcementTypes) self.comboBoxType.set(announcementTypes[0]) self.comboBoxType.grid(row=1, column=1, sticky=W) self.comboBoxType.bind('<<ComboboxSelected>>', self.updateType) self.scolledText = ScrolledText(self.frame, wrap=WORD, width=80, height=15) self.scolledText.grid(row=2, column=1, columnspan=2) self.scolledText.config(state=NORMAL) self.scolledText.insert(INSERT, self.announcement.message.as_string()) self.scolledText.config(state=DISABLED) self.buttonSendTestMail = Button(self.frame, text='Send Test Mail', command=self.sendTestMail) self.buttonSendTestMail.grid(row=4, column=1) self.buttonSendMail = Button(self.frame, text='Send Mail', command=self.sendMail) self.buttonSendMail.grid(row=4, column=2) self.checkButtonAttachmentAvailable = Checkbutton( self.frame, text="Attachments available") self.checkButtonAttachmentAvailable.grid(row=3, sticky=W) self.checkAttachments() def checkAttachments(self): key = self.announcement.getAttachmentKey() print("Info: Attachment key is " + str(key)) self.checkButtonAttachmentAvailable.config(state=NORMAL) if key is None: self.checkButtonAttachmentAvailable.deselect() self.buttonSendTestMail.config(state=NORMAL) self.buttonSendMail.config(state=NORMAL) else: if not self.announcement.attachmentsMissing(): self.checkButtonAttachmentAvailable.select() self.buttonSendTestMail.config(state=NORMAL) self.buttonSendMail.config(state=NORMAL) else: self.checkButtonAttachmentAvailable.deselect() # self.buttonSendTestMail.config(state=DISABLED) self.buttonSendMail.config(state=DISABLED) self.checkButtonAttachmentAvailable.config(state=DISABLED) def updateUser(self, *args): print(__class__.__name__ + "::" + sys._getframe().f_code.co_name) self.announcement.setUser(self.comboBoxUser.get()) self.scolledText.config(state=NORMAL) self.scolledText.delete(1.0, END) self.scolledText.insert(INSERT, self.announcement.message.as_string()) self.scolledText.config(state=DISABLED) self.checkAttachments() def updateType(self, *args): print(__class__.__name__ + "::" + sys._getframe().f_code.co_name) self.announcement.setMailType(self.comboBoxType.get()) self.scolledText.config(state=NORMAL) self.scolledText.delete(1.0, END) self.scolledText.insert(INSERT, self.announcement.message.as_string()) self.scolledText.config(state=DISABLED) self.checkAttachments() def sendTestMail(self): print(__class__.__name__ + "::" + sys._getframe().f_code.co_name) self.announcement.sendTestMail() def sendMail(self): print(__class__.__name__ + "::" + sys._getframe().f_code.co_name) pwDialog = PasswordDialog( self.frame, title=self.announcement.getFullAddressList()[0]) # print(pwDialog.result) if pwDialog.result: self.announcement.attach() self.announcement.sendMail(pwDialog.result) self.announcement.renderMessage()
text="INFO", width=10, bg="darkgoldenrod2", fg="black", command=llIIll) lIlIlI.grid(row=8, column=0) llllIl = IntVar() IIIIll = Checkbutton(IlIllI, text="Todo en una línea", variable=llllIl, onvalue=1, offvalue=0, fg="black", bg="gold") IIIIll.config(font=('Arial', 11)) IIIIll.grid(row=8, column=1) IlIIIl.grid(row=9, column=0) IlIlIl = Label(IlIllI, text="Lista Archivos", bg="gold", fg="black") IlIlIl.config(font=('Arial', 12)) IlIlIl.grid(pady=4, row=10, column=0) frame = Frame(width=380, height=200, bg="black", colormap="new") frame.grid(row=11, rowspan=5, column=0, columnspan=2) IIIIlI = tk.Scrollbar(frame, highlightbackground='indian red') IIIIlI.pack(side=tk.RIGHT, fill=tk.Y) lIIIlI = tk.Scrollbar(frame, orient=tk.HORIZONTAL)
class MyLogin(Dialog): def __init__(self, master, server=['', 0]): self.server = server super().__init__(master, title='Login Datenbank') def login(self): ''' Wenn Datenbank == True, dann erscheint die Login-Option. ''' if self.a.get() == True: self.dbnCbtn.config(state=DISABLED) self.EntryFrame.grid(column=0, row=5, pady=5, padx=5, sticky=NW) else: self.dbnCbtn.config(state=NORMAL) self.EntryFrame.grid_forget() def nologin(self): ''' Wenn option Datei gewählt ist ''' if self.b.get() == True: self.dbjCbtn.config(state=DISABLED) else: self.dbjCbtn.config(state=NORMAL) def body(self, master): ''' Auswahloption ''' self.GFrame = Frame(master) self.GFrame.pack() #self.GFrame.grid(column=0, row=0, pady=5, padx=5, sticky=NW) self.cbtnLabel = Label( self.GFrame, text='Möchten Sie sich mit der Datenbank verbinden?', font=13) self.cbtnLabel.grid(column=0, row=0, pady=5, padx=5, sticky=(NW)) self.a = BooleanVar() self.a.set(False) self.dbjCbtn = Checkbutton(self.GFrame, text='Ja, weiter zum Login.', var=self.a, command=self.login) self.dbjCbtn.grid(column=0, row=1, pady=5, padx=5, sticky=NW) self.dbjCbtn.config(state=DISABLED) self.b = BooleanVar() self.b.set(True) self.dbnCbtn = Checkbutton(self.GFrame, text='Nein, SOPs lokal verwalten.', var=self.b, command=self.nologin) self.dbnCbtn.grid(column=0, row=2, pady=5, padx=5, sticky=NW) ''' Login-Option erscheint, wenn Checkbox "Ja" ausgewählt ist. ''' self.EntryFrame = Frame(self.GFrame) self.EntryFrame.grid(column=0, row=5, pady=5, padx=5, sticky=NW) self.userLabel = Label(self.EntryFrame, text='Benutzername', font=13) self.userLabel.grid(column=0, row=9, pady=5, padx=5, sticky=(NW)) self.userEntry = Entry(self.EntryFrame, width=15, background='white') #Entry Feld self.userEntry.grid(column=1, row=9, pady=5, padx=5, sticky=(NW)) self.pwLabel = Label(self.EntryFrame, text='Passwort', font=13) self.pwLabel.grid(column=0, row=10, pady=5, padx=5, sticky=(NW)) self.pwEntry = Entry(self.EntryFrame, width=15, background='white') #Entry Feld self.pwEntry.grid(column=1, row=10, pady=5, padx=5, sticky=(NW)) self.hostLabel = Label(self.EntryFrame, text='Host', font=13) self.hostLabel.grid(column=0, row=11, pady=5, padx=5, sticky=(NW)) self.hostEntry = Entry(self.EntryFrame, width=15, background='white') #Entry Feld self.hostEntry.insert(0, self.server[0]) self.hostEntry.grid(column=1, row=11, pady=5, padx=5, sticky=(NW)) self.portLabel = Label(self.EntryFrame, text='Port', font=13) self.portLabel.grid(column=0, row=12, pady=5, padx=5, sticky=(NW)) self.portEntry = Entry(self.EntryFrame, width=15, background='white', text=self.server[1]) #Entry Feld self.portEntry.insert(0, self.server[1]) self.portEntry.grid(column=1, row=12, pady=5, padx=5, sticky=(NW)) self.EntryFrame.grid_forget() def apply(self): if self.a.get() == True: cred = [ self.userEntry.get(), self.pwEntry.get(), \ self.hostEntry.get(), int(self.portEntry.get()) ] else: cred = None self.result = cred
class CheckBox(ScheduleMixin, DestroyMixin, EnableMixin, FocusMixin, DisplayMixin, ReprMixin): def __init__(self, master, text, command=None, grid=None, align=None): self._text = str(text) self.description = "[CheckBox] object with text \"" + self._text + "\"" self._value = IntVar() # Create a tk Checkbutton object within this object self.tk = Checkbutton(master.tk, text=text, variable=self._value) # Add a command if there was one if command is not None: self.tk.config(command=command) utils.auto_pack(self, master, grid, align) # PROPERTIES # ---------------------------------- # Whether the box is checked or not @property def value(self): return (self._value.get()) # Set whether the box is checked or not @value.setter def value(self, value): try: value = int(value) if value in [0, 1]: self._value.set(value) except ValueError: utils.error_format("You can only set the value of " + self.description + " to either 0 (not checked) or 1 (checked)") # The text associated with this box @property def text(self): return (self._text) # Set whether the box is checked or not @text.setter def text(self, text): self._text = str(text) self.tk.config(text=self._text) self.description = "[CheckBox] object with text \"" + str(self._text) + "\"" # METHODS # ------------------------------------------- def toggle(self): self.tk.toggle() # DEPRECATED METHODS # -------------------------------------------- # Return text associated with this checkbox def get_text(self): return self._text utils.deprecated("CheckBox get_text() is deprecated. Please use the text property instead.") # Return the value (1 or 0) of the box def get_value(self): return self._value.get() utils.deprecated("CheckBox get_value() is deprecated. Please use the value property instead.") # Change text def change_text(self, newtext): self._text = str(newtext) self.tk.config(text=self._text) self.description = "[CheckBox] object with text " + str(self._text) utils.deprecated("CheckBox change_text() is deprecated. Please use the text property instead.")
class Notifier(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.text_clicked = False self.time_clicked = False self.running = False self.afterv = [] self.max_tries = 5 self.initUI() def initUI(self): # Establish frames self.pack(side="top", fill="both", expand=True) self.top_frame = Frame(self) self.bottom_frame = Frame(self) self.top_frame.pack(side="top", fill="both", expand=False) self.bottom_frame.pack(side="bottom", fill="both", expand=True) self.top_top_frame = Frame(self.top_frame) self.top_top_frame.pack(side="top", fill="both", expand=False) self.bottom_top_frame = Frame(self.top_frame) self.bottom_top_frame.pack(side="bottom", fill="both", expand=False) # Entry combo box self.cboxv = StringVar(self.top_top_frame) self.cbox = Combobox(self.top_top_frame, value=self.cboxv, width=40) self.cbox['values'] = ("all", "FreeGamesOnSteam", "funny", "news") self.cbox.current(0) self.cbox.bind("<Button-1>", self.text_callback) self.cbox.bind("<Tab>", self.time_callback) self.cbox.pack(side="left", padx=10, pady=10, expand=True) # Entry time box self.tentry = Entry(self.top_top_frame, width=8, foreground='gray') self.tentry.bind("<Button-1>", self.time_callback) self.tentry.insert(0, "Time(s)") self.tentry.pack(side="left", padx=10, pady=10, expand=True) # Category drop-down menu self.category = StringVar(self.top_top_frame) self.category.set("hot") # default value self.omenu = OptionMenu(self.top_top_frame, self.category, "hot", "new", "top", "controversial", "rising") self.omenu.pack(side="right", padx=10, pady=10, expand=True) # Limit drop-down menu self.limit = IntVar(self.top_top_frame) self.limit.set(5) # default value self.lmenu = OptionMenu(self.top_top_frame, self.limit, *list(range(10))) self.lmenu.pack(side="right", padx=10, pady=10, expand=True) # Scan button self.scanb = Button(self.bottom_top_frame, text="Scan", command=self.scan_subreddit) self.scanb.pack(side="left", padx=10, pady=10, expand=True) self.parent.bind("<Return>", lambda x: self.scan_subreddit()) # Popup check self.checkvar = BooleanVar() self.check = Checkbutton(self.bottom_top_frame, text="Popup", variable=self.checkvar) self.check.pack(side="left", padx=10, pady=10, expand=True) # Continuous check self.contvar = BooleanVar() self.contb = Checkbutton(self.bottom_top_frame, text="Continuous", variable=self.contvar) self.contb.pack(side="left", padx=10, pady=10, expand=True) # Stop button self.stopb = Button(self.bottom_top_frame, text="Stop", command=self.stop_scanning, state="disabled") self.stopb.pack(side="right", padx=10, pady=10, expand=True) self.parent.bind("<Escape>", lambda x: self.stop_scanning()) # Results text box self.text = CustomText(self.bottom_frame, height=10, width=50) self.text.configure(state="disabled") self.text.pack(side="top", padx=10, pady=10, expand=True, fill="both") def text_callback(self, event=None): if not self.text_clicked: self.cbox.delete(0, "end") self.text_clicked = True def time_callback(self, event=None): if not self.time_clicked: self.tentry.delete(0, "end") self.tentry.config(foreground="black") self.time_clicked = True def scan_subreddit(self): self.running = True self.scanb.config(state="disabled") self.stopb.config(state="normal") self.omenu.config(state="disabled") self.lmenu.config(state="disabled") self.cbox.config(state="disabled") self.tentry.config(state="disabled") self.check.config(state="disabled") self.contb.config(state="disabled") self.parent.unbind("<Return>") # Clean text box self.text.config(state="normal") self.text.delete(1.0, 'end') self.text.config(state="disabled") # Get values from boxes sub_name = self.cbox.get() cat = self.category.get() self.slimit = self.limit.get() self.popup = self.checkvar.get() self.cont = self.contvar.get() try: subreddit = reddit.subreddit(sub_name) except Exception: self.text.tinsert("Error: insert a subreddit" + '\n') self.stop_scanning() return try: self.stime = max(0, int(self.tentry.get())) except Exception: self.text.tinsert("Error: time must be a number" + '\n') self.stop_scanning() return self.text.tinsert("Info: getting " + cat + " posts from /r/" + sub_name + '\n') self.subcat = get_subreddit_cat(subreddit, cat) self.tries = 0 self.done_trying = False self.started_managing = False self.done_managing = False self.submissions = None self.get_results() def stop_scanning(self): self.running = False self.scanb.config(state="normal") self.stopb.config(state="disabled") self.omenu.config(state="normal") self.lmenu.config(state="normal") self.cbox.config(state="normal") self.tentry.config(state="normal") self.check.config(state="normal") self.contb.config(state="normal") self.parent.bind("<Return>", lambda x: self.scan_subreddit()) for a in self.afterv: self.parent.after_cancel(a) del self.afterv[:] def get_results(self): if self.running: now = time.time() if not self.done_trying: if self.tries < self.max_tries: try: self.submissions = [ x for x in self.subcat(limit=self.slimit) if (now - x.created_utc) < self.stime ] self.done_trying = True except Exception: self.text.tinsert("Error: [" + nows() + "] try n. " + str(self.tries + 1) + ", cannot access subreddit" + '\n') self.tries += 1 self.afterv.append( self.parent.after(5000, self.get_results)) else: self.text.tinsert( "Error: [" + nows() + "] couldn't access subreddit. Stopping scan." + '\n') self.stop_scanning() self.done_trying = True self.tries = 0 if self.done_trying: if not self.submissions: if not self.started_managing: self.text.tinsert("Info: [" + nows() + "] no results found" '\n') self.done_managing = True else: if not self.started_managing: self.text.tinsert("Info: [" + nows() + "] " + str(len(self.submissions)) + " results found" '\n') self.started_managing = True s = self.submissions[0] self.text.tinsert("Title: " + convert65536(s.title) + '\n') self.text.tinsert("Url: " + s.url + '\n') self.text.tinsert("Created: " + pretty_date(s) + '\n\n') self.parent.update_idletasks() if self.popup: if sys.platform.startswith('win'): import winsound winsound.PlaySound("media/jamaica.wav", winsound.SND_FILENAME) Dialog(self.parent, s.url, s.title) self.submissions = self.submissions[1:] self.afterv.append( self.parent.after(1000, self.get_results)) if self.done_managing: if self.cont: self.text.tinsert( "Info: [" + nows() + "] continuous mode, will check again in " + str(self.stime) + " seconds\n\n") self.afterv.append( self.parent.after(self.stime * 1000, self.get_results)) self.done_trying = False self.started_managing = False self.done_managing = False else: self.text.tinsert("Info: [" + nows() + "] scanning finished" '\n') self.stop_scanning()
class SettingsFrame(Frame): """ Settings frame class. """ def __init__(self, app, *args, **kwargs): """ Constructor. :param Frame app: reference to main tkinter application :param args: optional args to pass to Frame parent class :param kwargs: optional kwargs to pass to Frame parent class """ self.__app = app # Reference to main application class self.__master = self.__app.get_master() # Reference to root class (Tk) Frame.__init__(self, self.__master, *args, **kwargs) self._protocol = IntVar() self._raw = IntVar() self._autoscroll = IntVar() self._maxlines = IntVar() self._webmap = IntVar() self._mapzoom = IntVar() self._units = StringVar() self._format = StringVar() self._datalog = IntVar() self._record_track = IntVar() self._show_zerosig = IntVar() self._show_legend = IntVar() self._validsettings = True self._logpath = None self._trackpath = None self._img_conn = ImageTk.PhotoImage(Image.open(ICON_CONN)) self._img_disconn = ImageTk.PhotoImage(Image.open(ICON_DISCONN)) self._img_ubxconfig = ImageTk.PhotoImage(Image.open(ICON_UBXCONFIG)) self._img_dataread = ImageTk.PhotoImage(Image.open(ICON_LOGREAD)) self._body() self._do_layout() self._reset() def _body(self): """ Set up frame and widgets. """ for i in range(4): self.grid_columnconfigure(i, weight=1) self.grid_rowconfigure(0, weight=1) self.option_add("*Font", self.__app.font_sm) # serial port configuration panel self._frm_serial = SerialConfigFrame(self, preselect=KNOWNGPS, timeouts=TIMEOUTS, bpsrates=BPSRATES) # connection buttons self._frm_buttons = Frame(self) self._btn_connect = Button( self._frm_buttons, width=45, height=35, image=self._img_conn, command=lambda: self.__app.serial_handler.connect(), ) self._btn_disconnect = Button( self._frm_buttons, width=45, height=35, image=self._img_disconn, command=lambda: self.__app.serial_handler.disconnect(), state=DISABLED, ) self._btn_connect_file = Button( self._frm_buttons, width=45, height=35, image=self._img_dataread, command=lambda: self._on_data_stream(), ) self._lbl_status_preset = Label(self._frm_buttons, font=self.__app.font_md2, text="") # Other configuration options self._frm_options = Frame(self) self._lbl_protocol = Label(self._frm_options, text=LBLPROTDISP) self._rad_nmea = Radiobutton(self._frm_options, text="NMEA", variable=self._protocol, value=NMEA_PROTOCOL) self._rad_ubx = Radiobutton(self._frm_options, text="UBX", variable=self._protocol, value=UBX_PROTOCOL) self._rad_all = Radiobutton(self._frm_options, text="ALL", variable=self._protocol, value=MIXED_PROTOCOL) self._lbl_consoledisplay = Label(self._frm_options, text=LBLDATADISP) self._rad_parsed = Radiobutton(self._frm_options, text="Parsed", variable=self._raw, value=0) self._rad_raw = Radiobutton(self._frm_options, text="Raw", variable=self._raw, value=1) self._lbl_format = Label(self._frm_options, text="Degrees Format") self._spn_format = Spinbox( self._frm_options, values=(DDD, DMS, DMM), width=6, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._format, ) self._lbl_units = Label(self._frm_options, text="Units") self._spn_units = Spinbox( self._frm_options, values=(UMM, UIK, UI, UMK), width=13, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._units, ) self._chk_scroll = Checkbutton(self._frm_options, text="Autoscroll", variable=self._autoscroll) self._spn_maxlines = Spinbox( self._frm_options, values=("100", "200", "500", "1000", "2000"), width=6, readonlybackground=ENTCOL, wrap=True, textvariable=self._maxlines, state=READONLY, ) self._chk_webmap = Checkbutton( self._frm_options, text="Web Map Zoom", variable=self._webmap, command=lambda: self._on_webmap(), ) self._scl_mapzoom = Scale( self._frm_options, from_=1, to=20, orient=HORIZONTAL, relief="sunken", bg=ENTCOL, variable=self._mapzoom, ) self._chk_zerosig = Checkbutton(self._frm_options, text=LBLSHOWNULL, variable=self._show_zerosig) self._chk_legend = Checkbutton(self._frm_options, text=LBLLEGEND, variable=self._show_legend) self._chk_datalog = Checkbutton( self._frm_options, text=LBLDATALOG, variable=self._datalog, command=lambda: self._on_data_log(), ) self._chk_recordtrack = Checkbutton( self._frm_options, text=LBLTRACKRECORD, variable=self._record_track, command=lambda: self._on_record_track(), ) self._lbl_ubxconfig = Label(self._frm_options, text=LBLUBXCONFIG) self._btn_ubxconfig = Button( self._frm_options, width=45, height=35, text="UBX", image=self._img_ubxconfig, command=lambda: self._on_ubx_config(), state=DISABLED, ) def _do_layout(self): """ Position widgets in frame. """ self._frm_serial.grid(column=0, row=1, columnspan=4, padx=3, pady=3, sticky=(W, E)) ttk.Separator(self).grid(column=0, row=2, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_buttons.grid(column=0, row=3, columnspan=4, sticky=(W, E)) self._btn_connect.grid(column=0, row=0, padx=3, pady=3) self._btn_connect_file.grid(column=1, row=0, padx=3, pady=3) self._btn_disconnect.grid(column=3, row=0, padx=3, pady=3) ttk.Separator(self).grid(column=0, row=7, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_options.grid(column=0, row=8, columnspan=4, sticky=(W, E)) self._lbl_protocol.grid(column=0, row=0, padx=3, pady=3, sticky=(W)) self._rad_nmea.grid(column=1, row=0, padx=0, pady=0, sticky=(W)) self._rad_ubx.grid(column=2, row=0, padx=0, pady=0, sticky=(W)) self._rad_all.grid(column=3, row=0, padx=0, pady=0, sticky=(W)) self._lbl_consoledisplay.grid(column=0, row=1, padx=2, pady=3, sticky=(W)) self._rad_parsed.grid(column=1, row=1, padx=1, pady=3, sticky=(W)) self._rad_raw.grid(column=2, row=1, padx=2, pady=3, sticky=(W)) self._lbl_format.grid(column=0, row=2, padx=3, pady=3, sticky=(W)) self._spn_format.grid(column=1, row=2, padx=2, pady=3, sticky=(W)) self._lbl_units.grid(column=0, row=3, padx=3, pady=3, sticky=(W)) self._spn_units.grid(column=1, row=3, columnspan=3, padx=2, pady=3, sticky=(W)) self._chk_scroll.grid(column=0, row=4, padx=3, pady=3, sticky=(W)) self._spn_maxlines.grid(column=1, row=4, columnspan=3, padx=3, pady=3, sticky=(W)) self._chk_webmap.grid(column=0, row=5, padx=3, pady=3, sticky=(W)) self._scl_mapzoom.grid(column=1, row=5, columnspan=3, sticky=(W)) self._chk_legend.grid(column=0, row=6, padx=3, pady=3, sticky=(W)) self._chk_zerosig.grid(column=1, row=6, columnspan=2, padx=3, pady=3, sticky=(W)) self._chk_datalog.grid(column=0, row=7, padx=3, pady=3, sticky=(W)) self._chk_recordtrack.grid(column=1, row=7, columnspan=2, padx=3, pady=3, sticky=(W)) ttk.Separator(self._frm_options).grid(column=0, row=8, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._lbl_ubxconfig.grid(column=0, row=9, padx=3, pady=3, sticky=(W)) self._btn_ubxconfig.grid(column=1, row=9, padx=3, pady=3, sticky=(W)) def _on_ubx_config(self, *args, **kwargs): # pylint: disable=unused-argument """ Open UBX configuration dialog panel. """ self.__app.ubxconfig() def _on_webmap(self): """ Reset webmap refresh timer """ self.__app.frm_mapview.reset_map_refresh() def _on_data_log(self): """ Start or stop data logger """ if self._datalog.get() == 1: self._logpath = self.__app.file_handler.set_logfile_path() if self._logpath is not None: self.__app.set_status("Data logging enabled: " + self._logpath, "green") else: self._datalog.set(False) else: self._logpath = None self._datalog.set(False) # self.__app.file_handler.close_logfile() self.__app.set_status("Data logging disabled", "blue") def _on_record_track(self): """ Start or stop track recorder """ if self._record_track.get() == 1: self._trackpath = self.__app.file_handler.set_trackfile_path() if self._trackpath is not None: self.__app.set_status( "Track recording enabled: " + self._trackpath, "green") else: self._record_track.set(False) else: self._trackpath = None self._record_track.set(False) # self.__app.file_handler.close_trackfile() self.__app.set_status("Track recording disabled", "blue") def _on_data_stream(self): """ Start data file streamer """ self._logpath = self.__app.file_handler.open_logfile_input() if self._logpath is not None: self.__app.set_status("") self.__app.serial_handler.connect_file() def _reset(self): """ Reset settings to defaults. """ self._protocol.set(MIXED_PROTOCOL) self._format.set(DDD) self._units.set(UMM) self._autoscroll.set(1) self._maxlines.set(300) self._raw.set(False) self._webmap.set(False) self._mapzoom.set(10) self._show_legend.set(True) self._show_zerosig.set(False) self._datalog.set(False) self._record_track.set(False) def enable_controls(self, status: int): """ Public method to enable and disable those controls which depend on connection status. :param int status: connection status as integer (0=Disconnected, 1=Connected to serial, 2=Cnnected to file, 3=No serial ports available) """ self._frm_serial.enable_controls(status) self._btn_connect.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE, NOPORTS) else NORMAL)) self._btn_disconnect.config( state=(DISABLED if status in (DISCONNECTED, NOPORTS) else NORMAL)) self._chk_datalog.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE, NOPORTS) else NORMAL)) self._chk_recordtrack.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE) else NORMAL)) self._btn_connect_file.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE) else NORMAL)) self._btn_ubxconfig.config( state=(DISABLED if status in (DISCONNECTED, CONNECTED_FILE, NOPORTS) else NORMAL)) self.__app.menu.options_menu.entryconfig( 0, state=(DISABLED if status in (CONNECTED_FILE, DISCONNECTED, NOPORTS) else NORMAL), ) def get_size(self) -> (int, int): """ Get current frame size. :return: (width, height) :rtype: tuple """ self.update_idletasks() # Make sure we know about any resizing return (self.winfo_width(), self.winfo_height()) def serial_settings(self) -> Frame: """ Return reference to common serial configuration panel :return: reference to serial form :rtype: Frame """ return self._frm_serial @property def protocol(self) -> int: """ Getter for displayed protocols :return: protocol displayed (0=NMEA, 1=UBX, 2=BOTH) :rtype: int """ return self._protocol.get() @property def raw(self) -> int: """ Getter for console display format :return: display format (0 - parsed, 1 = raw) :rtype: int """ return self._raw.get() @property def autoscroll(self) -> int: """ Getter for autoscroll flag :return: scroll setting (0 = no scroll, 1 = auto) :rtype: int """ return self._autoscroll.get() @property def maxlines(self) -> int: """ Getter for max console display lines :return: max lines in console display (default=300) :rtype: int """ return self._maxlines.get() @property def webmap(self) -> int: """ Getter for webmap flag :return: map type (0 = static map, 1 = dynamic web map) :rtype: int """ return self._webmap.get() @property def mapzoom(self) -> int: """ Getter for webmap zoom level :return: webmap zoom level (1-20) :rtype: int """ return self._mapzoom.get() @property def units(self) -> int: """ Getter for display units :return: "UMM" = metric m/s, "UMK" = metric kmph, "UI" = imperial mph, "UIK" = imperial knots :rtype: int """ return self._units.get() @property def format(self) -> str: """ Getter for degrees format :return: "DD.D" = decimal degrees, "DM.M" = degrees, decimal minutes, "D.M.S" = degrees, minutes, seconds :rtype: str """ return self._format.get() @property def logpath(self) -> str: """ Getter for datalog file path :return: datalog file path :rtype: str """ return self._logpath @property def datalogging(self) -> int: """ Getter for datalogging flag :return: 0 = no log, 1 = record datalog :rtype: int """ return self._datalog.get() @property def record_track(self) -> int: """ Getter for record track flag :return: 0 = no track, 1 = record track :rtype: int """ return self._record_track.get() @property def show_zero(self) -> int: """ Getter for zero signal flag :return: 0 = exclude, 1 = include :rtype: int """ return self._show_zerosig.get() @property def show_legend(self) -> int: """ Getter for graph legend flag :return: 0 = hide, 1 = show :rtype: int """ return self._show_legend.get()
lang.config(font=("Courier", 12), width=8) lang.place(x=20, y=50) file_button = Button(text=u'選取API金鑰', command=choose_file) file_button.config(font=("Courier", 12)) file_button.place(x=24, y=110) file_name = StringVar() file_name.set('') file_name_label = Label(root, textvariable=file_name, justify=LEFT, wraplengt=250) file_name_label.place(x=20, y=150) connect_int = IntVar() connect_check = Checkbutton(root, text=u"連接至unity\n(5067號埠)", variable=connect_int, onvalue=1, offvalue=0) connect_check.config(font=("Courier", 12)) connect_check.place(x=160, y=5) debug_int = IntVar() debug_check = Checkbutton(root, text=u"字幕顯示在螢幕", variable=debug_int, onvalue=1, offvalue=0) debug_check.config(font=("Courier", 12)) debug_check.place(x=160, y=50) file_button = Button(text=u'開始', command=execute) file_button.config(font=("Courier", 25)) file_button.place(x=160, y=80) root.mainloop()
class Display_Frame(tkinter.Frame): def __init__(self, root): super().__init__(root, width=1000, height=1000) self.angles = [] self.units_radio_rad = Radiobutton(self, variable=display_settings.AngleUnits, text="radians", value=display_settings.UNITS_RADIANS) self.units_radio_rad.place(y=10, x=20) self.units_radio_deg = Radiobutton(self, variable=display_settings.AngleUnits, text="degrees", value=display_settings.UNITS_DEGREES) self.units_radio_deg.place(y=30, x=20) self.angle_labels = [] self.angle_boxes = [] self.grid_lines_CB = Checkbutton(self, variable=display_settings.ShowGrid, text="Show Grid") self.grid_numbers_CB = Checkbutton(self, variable=display_settings.ShowGridNumbers, text="Show Grid Numbers") self.arm_bounds_CB = Checkbutton(self, variable=display_settings.ShowArmBounds, text="Show Arm Bounds") self.angle_text_CB = Checkbutton(self, variable=display_settings.ShowAngleText, text="Show Angle Text") self.angle_arc_CB = Checkbutton(self, variable=display_settings.ShowAngleArc, text="Show Angle Arc") self.fit_arm_button = tkinter.Button(self, text="Fit Arm") elements = [self.grid_lines_CB, self.grid_numbers_CB, self.arm_bounds_CB, self.angle_text_CB, self.angle_arc_CB, self.fit_arm_button] for i in range(len(elements)): elements[i].place(x=200, y=10 + i * 20) def bind_canvas(self, canvas): self.units_radio_rad.config(command=lambda self=self: [self.refresh_angle_elements(), canvas.update()]) self.units_radio_deg.config(command=lambda self=self: [self.refresh_angle_elements(), canvas.update()]) self.grid_lines_CB.config(command=canvas.update) self.grid_numbers_CB.config(command=canvas.update) self.arm_bounds_CB.config(command=canvas.update) self.angle_text_CB.config(command=canvas.update) self.angle_arc_CB.config(command=canvas.update) self.fit_arm_button.config(command=canvas.scale_to_fit_arm) def refresh_angle_elements(self): angle_mult = 1 if display_settings.AngleUnits.get() == display_settings.UNITS_DEGREES: angle_mult = (180 / 3.14159) for i in range(len(self.angles)): self.angle_boxes[i].config(state="normal") self.angle_boxes[i].delete(0, tkinter.END) angle = round(self.angles[i] * angle_mult, 3) self.angle_boxes[i].insert(0, str(angle)) self.angle_boxes[i].config(state="disabled") def set_elements(self, angles): self.angles = angles while len(self.angle_boxes) < len(angles): self.add_angle_element() while len(self.angle_boxes) > len(angles): self.remove_angle_element() self.refresh_angle_elements() def add_angle_element(self): index = len(self.angle_boxes) y_val = 70 + index * 20 label = tkinter.Label(self, text="Angle "+str(index+1)+":") label.place(x=20, y=y_val) a_box = tkinter.Entry(self, width=10, justify="center") a_box.place(x=100, y=y_val) a_box.delete(0, tkinter.END) a_box.insert(0, "0.0") a_box.config(state="disabled") self.angle_labels.append(label) self.angle_boxes.append(a_box) def remove_angle_element(self): self.angle_labels[-1].destroy() self.angle_labels = self.angle_labels[:-1] self.angle_boxes[-1].destroy() self.angle_boxes = self.angle_boxes[:-1]
class ManagerWindow: """ 主管理界面入口类,直接无参数创建对象即可。 """ # 窗口宽高 WIN_WIDTH = 800 WIN_HEIGHT = 600 def __init__(self): # 界面根节点 self.root = Tk() # 主窗口标题 self.root.title(MANAGER_TITLE) # 读取config self.config_dict = ConfigOperation.get_dir_from_file() # 主窗口分辨率 self.root.geometry("%sx%s+%s+%s" % ( self.WIN_WIDTH, self.WIN_HEIGHT, int((self.root.winfo_screenwidth() - self.WIN_WIDTH) / 2), int((self.root.winfo_screenheight() - self.WIN_HEIGHT) / 2) )) self.root.minsize(self.WIN_WIDTH, self.WIN_HEIGHT) # 选项卡 self.tab_main = Notebook(self.root) self.tab_main.pack(expand=True, fill=BOTH) # 登录选项卡 self.frame_login = Frame(self.tab_main, bg=BG_COLOR) self.frame_login.pack(side=TOP) self.tab_main.add(self.frame_login, text=TAB_NAME_LIST["login"]["text"]) # 管理选项卡 self.frame_manage = Frame(self.tab_main, bg=BG_COLOR) self.tab_main.add(self.frame_manage, text=TAB_NAME_LIST["manage"]["text"]) # 好友选项卡 self.frame_friend = Frame(self.tab_main, bg=BG_COLOR) self.frame_friend.pack(side=TOP) self.tab_main.add(self.frame_friend, text=TAB_NAME_LIST["friends"]["text"]) # 群选项卡 self.frame_group = Frame(self.tab_main, bg=BG_COLOR) self.frame_group.pack(side=TOP) self.tab_main.add(self.frame_group, text=TAB_NAME_LIST["groups"]["text"]) # 插件选项卡 self.frame_plugin = Frame(self.tab_main, bg=BG_COLOR) self.frame_plugin.pack(side=TOP) self.tab_main.add(self.frame_plugin, text=TAB_NAME_LIST["plugins"]["text"]) # 初始化登录选项卡 self.__init_login_tab() # 初始化好友选项卡 self.__init_friend_tab() # 初始化群选项卡 self.__init_group_tab() # 初始化管理选项卡 self.__init_manage_tab() # 初始化插件选项卡 self.__init_plugin_tab() # 关闭窗口自动释放Session self.root.protocol("WM_DELETE_WINDOW", lambda: self.__on_close_root()) # 刷新显示 self.__refresh() # 运行相关线程 fetch_message_thread = FetchMessageThread() fetch_message_thread.daemon = True fetch_message_thread.start() # 运行插件初始化方法 PluginHandler.call_init() # 执行自动连接一次 self.__auto_connect() # 显示 self.root.mainloop() def __init_login_tab(self): """ 初始化登录选项卡界面 :return: 无 """ # 左边列表的frame frame_login_list = Frame(self.frame_login, bg=BG_COLOR) frame_login_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 列表,用于保存连接记录 self.treeview_login_list = Treeview( frame_login_list, columns=[ LOGIN_GUIDE["host"], LOGIN_GUIDE["port"], LOGIN_GUIDE["authkey"], LOGIN_GUIDE["qq"] ], show="headings", selectmode=BROWSE ) self.treeview_login_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_login_list.column( LOGIN_GUIDE["host"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["host"], text=LOGIN_GUIDE["host"] ) self.treeview_login_list.column( LOGIN_GUIDE["port"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["port"], text=LOGIN_GUIDE["port"] ) self.treeview_login_list.column( LOGIN_GUIDE["authkey"], width=40 ) self.treeview_login_list.heading( LOGIN_GUIDE["authkey"], text=LOGIN_GUIDE["authkey"] ) self.treeview_login_list.column( LOGIN_GUIDE["qq"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["qq"], text=LOGIN_GUIDE["qq"] ) # 设定双击事件 self.treeview_login_list.bind( "<Double-Button-1>", lambda event: self.__on_double_click_login_list_content() ) # 设定登录列表的滚动条 scrollbar_login_list = Scrollbar(frame_login_list) scrollbar_login_list.pack(fill="y", expand=True) self.treeview_login_list.config(yscrollcommand=scrollbar_login_list.set) scrollbar_login_list.config(command=self.treeview_login_list.yview) # 设置列表右键菜单 self.treeview_login_list.bind("<Button-3>", self.__show_login_list_pop_up_menu) # 登录界面显示的那一坨 frame_login_menu = Frame(self.frame_login, bg=BG_COLOR) frame_login_menu.pack(side=LEFT, padx=5, pady=5) # mirai端地址 Label(frame_login_menu, text=LOGIN_GUIDE["host"], bg=BG_COLOR).grid(row=0, sticky=E, padx=5, pady=5) self.entry_host = Entry(frame_login_menu) self.entry_host.grid(row=0, column=1, sticky=W, padx=5, pady=5) # mirai端端口号 Label(frame_login_menu, text=LOGIN_GUIDE["port"], bg=BG_COLOR).grid(row=1, sticky=E, padx=5, pady=5) self.entry_port = Entry(frame_login_menu) self.entry_port.grid(row=1, column=1, sticky=W, padx=5, pady=5) # mirai端http授权码 Label(frame_login_menu, text=LOGIN_GUIDE["authkey"], bg=BG_COLOR).grid( row=2, sticky=E, padx=5, pady=5 ) self.entry_authkey = Entry(frame_login_menu, show=PWD_CHAR_CIRCLE) self.entry_authkey.grid(row=2, column=1, sticky=W, padx=5, pady=5) # 用于激活sessioKey的qq号码 Label(frame_login_menu, text=LOGIN_GUIDE["qq"], bg=BG_COLOR).grid( row=3, sticky=E, padx=5, pady=5 ) self.entry_qq = Entry(frame_login_menu) self.entry_qq.grid(row=3, column=1, sticky=W, padx=5, pady=5) # 自动连接复选框 self.auto_connect_var = BooleanVar() self.checkbutton_auto_connect = Checkbutton( frame_login_menu, text=AUTO_CONNECT_GUIDE, onvalue=True, offvalue=False, variable=self.auto_connect_var, bg=BG_COLOR ) self.checkbutton_auto_connect.grid(row=4, column=0, padx=5, pady=5, columnspan=2) # 连接按钮 self.btn_connect = Button( frame_login_menu, text=BTN_TEXT_CONN["connect"], width=15, command=lambda: self.__on_click_connect_event(), ) self.btn_connect.grid(row=5, columnspan=2, padx=5, pady=5) # 添加到登录列表按钮 self.btn_save_login = Button( frame_login_menu, width=15, text=BTN_TEXT_ADD_LOGIN, command=lambda: self.__on_click_add_to_login_list() ) self.btn_save_login.grid(row=6, columnspan=2, padx=5, pady=5) # 状态栏 self.label_login_status_bar = Label( self.root, text=LOGIN_STATUS_BAR_TEXT["notConnect"], fg=STATUS_BAR_COLOR["normal"] ) self.label_login_status_bar.pack(side=LEFT) # 下面开始从config中将内容填充进文本框中 self.entry_host.delete(0, END) self.entry_host.insert(END, self.config_dict["lastConnection"]["host"]) self.entry_port.delete(0, END) self.entry_port.insert(END, self.config_dict["lastConnection"]["port"]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, self.config_dict["lastConnection"]["authkey"]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, self.config_dict["lastConnection"]["qq"]) # 自动连接复选框内容 self.auto_connect_var.set(self.config_dict["autoConnect"]) def __init_friend_tab(self): """ 初始化好友选项卡内容 :return: 无 """ # 创建好友列表框架 frame_friend_list = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_friend_send = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_friend_list = Treeview( frame_friend_list, columns=[ FRIEND_GUIDE["qq"], FRIEND_GUIDE["nickname"], FRIEND_GUIDE["remark"] ], show="headings", selectmode=BROWSE ) self.treeview_friend_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_friend_list.column( FRIEND_GUIDE["qq"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["qq"], text=FRIEND_GUIDE["qq"] ) self.treeview_friend_list.column( FRIEND_GUIDE["nickname"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["nickname"], text=FRIEND_GUIDE["nickname"] ) self.treeview_friend_list.column( FRIEND_GUIDE["remark"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["remark"], text=FRIEND_GUIDE["remark"] ) # 设定好友列表的滚动条 scrollbar_friend_list = Scrollbar(frame_friend_list) scrollbar_friend_list.pack(fill="y", expand=True) self.treeview_friend_list.config(yscrollcommand=scrollbar_friend_list.set) scrollbar_friend_list.config(command=self.treeview_friend_list.yview) # 刷新列表按钮 Button( frame_friend_send, text=BTN_FRIEND_REFRESH, command=lambda: self.__on_click_refresh_friend_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_friend_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_friend_send = Text(frame_friend_send, width=30, height=5) self.text_friend_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_friend_send, text=BTN_SEND, command=lambda: self.__on_click_send_friend_message() ).grid(row=3, padx=5, pady=5) def __init_group_tab(self): """ 初始化群选项卡内容 :return: 无 """ # 创建好友列表框架 frame_group_list = Frame(self.frame_group, bg=BG_COLOR) frame_group_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_group_send = Frame(self.frame_group, bg=BG_COLOR) frame_group_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_group_list = Treeview( frame_group_list, columns=[ GROUP_GUIDE["group"], GROUP_GUIDE["name"], GROUP_GUIDE["permission"] ], show="headings", selectmode=BROWSE ) self.treeview_group_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_group_list.column( GROUP_GUIDE["group"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["group"], text=GROUP_GUIDE["group"] ) self.treeview_group_list.column( GROUP_GUIDE["name"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["name"], text=GROUP_GUIDE["name"] ) self.treeview_group_list.column( GROUP_GUIDE["permission"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["permission"], text=GROUP_GUIDE["permission"] ) # 设定群列表的滚动条 scrollbar_group_list = Scrollbar(frame_group_list) scrollbar_group_list.pack(fill="y", expand=True) self.treeview_group_list.config(yscrollcommand=scrollbar_group_list.set) scrollbar_group_list.config(command=self.treeview_group_list.yview) # 刷新列表按钮 Button( frame_group_send, text=BTN_GROUP_REFRESH, command=lambda: self.__on_click_refresh_group_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_group_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_group_send = Text(frame_group_send, width=30, height=5) self.text_group_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_group_send, text=BTN_SEND, command=lambda: self.__on_click_send_group_message() ).grid(row=3, padx=5, pady=5) def __init_manage_tab(self): """ 初始化管理选项卡 :return: 无 """ f_manage = Frame(self.frame_manage, bg=BG_COLOR) f_manage.pack(padx=5, pady=5, expand=True) # 指定头指示 Label(f_manage, text=MANAGE_GUIDE["commandHead"], bg=BG_COLOR).grid( row=0, column=0, padx=5, pady=5, sticky=E ) # 指令头文本框 self.entry_command_head = Entry(f_manage) self.entry_command_head.grid(row=0, column=1, padx=5, pady=5, sticky=EW) # 调试复选框 self.debug_var = BooleanVar() checkbutton_debug = Checkbutton( f_manage, text=MANAGE_GUIDE["debug"], onvalue=True, offvalue=False, variable=self.debug_var, bg=BG_COLOR ) checkbutton_debug.grid(row=1, column=0, columnspan=3, padx=5, pady=5) # 启用机器人 self.enable_var = BooleanVar() checkbutton_enable = Checkbutton( f_manage, text=MANAGE_GUIDE["enable"], onvalue=True, offvalue=False, variable=self.enable_var, bg=BG_COLOR ) checkbutton_enable.grid(row=2, column=0, columnspan=3, padx=5, pady=5) # 配置保存 Button( f_manage, text=MANAGE_GUIDE["saveConfig"], command=self.__on_click_save_config ).grid( row=3, column=1, padx=5, pady=5, sticky=EW ) # bot管理qq列表 self.treeview_op_list = Treeview( f_manage, columns=[ MANAGE_GUIDE["botOpQQ"] ], show="headings", selectmode=BROWSE ) self.treeview_op_list.column(MANAGE_GUIDE["botOpQQ"], width=200) self.treeview_op_list.heading(MANAGE_GUIDE["botOpQQ"], text=MANAGE_GUIDE["botOpQQ"]) self.treeview_op_list.grid( row=4, column=0, columnspan=3, rowspan=10, sticky=EW ) # 列表右键 self.treeview_op_list.bind("<Button-3>", self.__show_op_list_pop_up_menu) # 添加管理标签 Label(f_manage, text=MANAGE_GUIDE["addOpQQ"], bg=BG_COLOR).grid(row=14, column=0, padx=5, pady=5) # 添加管理文本框 self.entry_add_op = Entry(f_manage) self.entry_add_op.grid(row=14, column=1, padx=5, pady=5) # 添加添加按钮 Button( f_manage, text=MANAGE_GUIDE["btnAddOpQQ"], command=lambda: self.__on_click_add_op() ).grid(row=14, column=2, padx=5, pady=5, sticky=EW) def __init_plugin_tab(self): """ 初始化插件选项卡 :return: 无 """ # 指示标签 Label(self.frame_plugin, text=PLUGIN_LABEL_TEXT, bg=BG_COLOR).pack(side=TOP) # 插件列表frame frame_plugin_list = Frame(self.frame_plugin, bg=BG_COLOR) frame_plugin_list.pack( side=TOP, expand=True, fill=BOTH, padx=5, pady=5 ) # 插件列表 self.treeview_plugin_list = Treeview( frame_plugin_list, columns=[ PLUGIN_GUIDE["pluginName"] ], show="headings", selectmode=BROWSE ) self.treeview_plugin_list.pack(fill=BOTH, expand=True, side=LEFT) self.treeview_plugin_list.column(PLUGIN_GUIDE["pluginName"]) self.treeview_plugin_list.heading(PLUGIN_GUIDE["pluginName"], text=PLUGIN_GUIDE["pluginName"]) # 设定插件列表滚动条 scrollbar_plugin_list = Scrollbar(frame_plugin_list) scrollbar_plugin_list.pack(fill="y", expand=True) self.treeview_plugin_list.config(yscrollcommand=scrollbar_plugin_list.set) scrollbar_plugin_list.config(command=self.treeview_plugin_list.yview) def __on_click_connect_event(self): """ 点击连接按钮事件 :return: 无 """ if not GlobalValues.is_connected: # 如果是要连接 # 存到全局使用变量 GlobalValues.conn_host = self.entry_host.get() GlobalValues.conn_port = self.entry_port.get() GlobalValues.conn_authkey = self.entry_authkey.get() try: # 转换为整型后保存 GlobalValues.conn_qq = int(self.entry_qq.get()) except ValueError: self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["wrongQQ"], fg=STATUS_BAR_COLOR["failed"]) return # 修改界面上的一些内容为不可修改 self.__set_login_tools_active(False) # 修改按钮内容 self.btn_connect.config(text=BTN_TEXT_CONN["disconnect"]) # 修改状态栏内容 self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["connecting"], fg=STATUS_BAR_COLOR["normal"]) # 调用连接 try: Conn.new_session_key() except ( requests.exceptions.InvalidURL, requests.exceptions.ConnectionError, ): # 连接错误 # 错误信息显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connectFailed"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except WrongAuthkeyException: # 授权码错误 # 显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["wrongAuthkey"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except BotNotExistException: # bot不存在错误 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["qqNotExist"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connected"], fg=STATUS_BAR_COLOR["passed"] ) # 修改连接状态值 GlobalValues.is_connected = True # 修改上次连接键值对 ConfigOperation.modify_dict("lastConnection", { "host": GlobalValues.conn_host, "port": GlobalValues.conn_port, "authkey": GlobalValues.conn_authkey, "qq": GlobalValues.conn_qq }) # 修改文件中自动连接开关 ConfigOperation.modify_dict("autoConnect", self.auto_connect_var.get()) else: # 如果要断开连接 # 修改文本框为可修改 self.__set_login_tools_active(True) # 修改按钮名称 self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) # 修改属性值 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["disconnectSuccess"], fg=STATUS_BAR_COLOR["normal"] ) # 释放session Conn.release_session_key() # 修改连接状态值 GlobalValues.is_connected = False def __set_login_tools_active(self, active: bool): """ 修改界面上的一些内容为不可修改 :param active: bool,如果为False则禁用掉文本框,否则启用 :return: 无 """ if active: self.entry_host.config(state=ACTIVE) self.entry_port.config(state=ACTIVE) self.entry_authkey.config(state=ACTIVE) self.entry_qq.config(state=ACTIVE) self.checkbutton_auto_connect.config(state=ACTIVE) else: self.entry_host.config(state=DISABLED) self.entry_port.config(state=DISABLED) self.entry_authkey.config(state=DISABLED) self.entry_qq.config(state=DISABLED) self.checkbutton_auto_connect.config(state=DISABLED) def __on_close_root(self): """ 关闭窗口的事件 :return: 无 """ # 如果正在连接则释放连接 if GlobalValues.is_connected: Conn.release_session_key() # 杀掉root self.root.destroy() def __refresh(self): """ 用于刷新界面,在必要时调用 :return: 无 """ def refresh_login_list(): """ 刷新登录列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_login_list.delete(*self.treeview_login_list.get_children()) # 把登录列表内容添加到显示中 for one_record in LoginListOperation.get_list_from_file(): self.treeview_login_list.insert("", index=END, values=( one_record["host"], one_record["port"], one_record["authkey"], one_record["qq"] )) def refresh_op_list(): """ 刷新bot管理员qq列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_op_list.delete(*self.treeview_op_list.get_children()) # 把内容添加到显示中 for one_record in OpListOperation.get_list(): self.treeview_op_list.insert("", index=END, values=( one_record )) def refresh_config(): """ 刷新配置 :return: 无 """ # 重新获取config self.config_dict = ConfigOperation.get_dir_from_file() # 将文件中的内容显示到界面中 self.entry_command_head.delete(0, END) self.entry_command_head.insert(END, self.config_dict["commandHead"]) # 设置复选框默认勾选 self.debug_var.set(self.config_dict["debug"]) self.enable_var.set(self.config_dict["enable"]) # 将内容设置到全局变量 GlobalValues.command_head = self.config_dict["commandHead"] GlobalValues.debug_var = self.debug_var GlobalValues.enable_var = self.enable_var def refresh_plugin_list(): # 获取插件名称 plugin_names = PluginHandler.get_plugin_name_list() # 显示 self.treeview_plugin_list.delete(*self.treeview_plugin_list.get_children()) for name in plugin_names: self.treeview_plugin_list.insert("", index=END, values=( name )) # 调用刷新登录列表 refresh_login_list() # 调用刷新op列表 refresh_op_list() # 刷新config显示 refresh_config() # 刷新插件列表显示 refresh_plugin_list() def __on_click_add_to_login_list(self): """ 将填写内容添加到列表中 :return: 无 """ # 非空检测 if [ self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ] == [""] * 4: return # 调用添加登录项方法 LoginListOperation.add_to_list( self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ) # 刷新显示 self.__refresh() def __on_double_click_login_list_content(self): """ 双击登录列表项目时,自动填充到右侧 :return: 无 """ # 获取item的值 item_list = self.treeview_login_list.item(self.treeview_login_list.focus(), "values") # 获取需要的项目并设置 self.entry_host.delete(0, END) self.entry_host.insert(END, item_list[0]) self.entry_port.delete(0, END) self.entry_port.insert(END, item_list[1]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, item_list[2]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, item_list[3]) def __show_login_list_pop_up_menu(self, event): """ 显示右键菜单 :param event: 事件 :return: 无 """ def on_delete_event(item_id): """ 删除选项的事件 :return: 无 """ # 删除该项 LoginListOperation.remove_from_list(*self.treeview_login_list.item(item_id, "values")) self.treeview_login_list.delete(item_id) self.__refresh() # 获取选择对象 iid = self.treeview_login_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if iid: self.treeview_login_list.selection_set(iid) menu_pop_up = Menu(self.treeview_login_list, tearoff=False) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event(iid) ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_refresh_friend_list_event(self): """ 点击刷新好友列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 friend_list = Conn.get_friend_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_friend_list.delete(*self.treeview_friend_list.get_children()) # 解析friend_list for friend_block in friend_list: self.treeview_friend_list.insert("", index=END, values=( friend_block["id"], friend_block["nickname"], friend_block["remark"] )) def __on_click_refresh_group_list_event(self): """ 点击刷新群列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 group_list = Conn.get_group_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_group_list.delete(*self.treeview_group_list.get_children()) # 解析group_list for group_block in group_list: self.treeview_group_list.insert("", index=END, values=( group_block["id"], group_block["name"], group_block["permission"] )) def __on_click_send_friend_message(self): """ 点击发送消息给好友按钮 :return: 无 """ # 获取到选中好友的值列表 value_list = self.treeview_friend_list.item(self.treeview_friend_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_friend_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_friend_message(qq, message_chain) self.text_friend_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_send_group_message(self): """ 点击发送消息给群按钮 :return: 无 """ # 获取到选中群的值列表 value_list = self.treeview_group_list.item(self.treeview_group_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_group_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_group_message(qq, message_chain) self.text_group_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_add_op(self): """ 点击添加op按钮事件 :return: 无 """ content = self.entry_add_op.get() # 如果添加op的文本框中没有东西,则不添加 if content == "": return # 如果转换数字出错则不添加 try: op_qq = int(content) except ValueError: return # 添加到op列表中 OpListOperation.add_to_list(op_qq) # 刷新显示 self.__refresh() def __show_op_list_pop_up_menu(self, event): """ op列表右键菜单 :return: 无 """ def on_delete_event(): """ 删除选项的事件 :return: 无 """ # 删除该项 # 注意此处的强转,由于能够保证显示出来的内容一定只含有数字,故可以直接转换 OpListOperation.remove_from_list(int(self.treeview_op_list.item(op_qq, "values")[0])) self.treeview_op_list.delete(op_qq) self.__refresh() # 获取选择对象 op_qq = self.treeview_op_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if op_qq: menu_pop_up = Menu(self.treeview_op_list, tearoff=False) self.treeview_op_list.selection_set(op_qq) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event() ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_save_config(self): """ 点击保存配置事件 :return: 无 """ content = self.entry_command_head.get() # 如果为空,则不存入,但是刷新 # 这样是为了保证点击后会显示原来的设置 if content == "": self.__refresh() return ConfigOperation.modify_dict("commandHead", content) ConfigOperation.modify_dict("debug", self.debug_var.get()) ConfigOperation.modify_dict("enable", self.enable_var.get()) # 刷新 self.__refresh() # 弹出对话框 messagebox.showinfo(message=MANAGE_GUIDE["successSaveCommandHeadMsg"]) def __auto_connect(self): if self.config_dict["autoConnect"]: self.__on_click_connect_event()
class line_item: def __init__(self, parameter_name, which_frame, row_number, start_value, end_value): #Label Label(which_frame, text=parameter_name + ": ").grid(row=row_number, column=0) self.current_value = start_value #Start Value self.start_entry = Entry(which_frame, justify="right", width=8) self.start_entry.insert("end", str(start_value)) self.start_entry.grid(row=row_number, column=1) #End Value self.end_entry = Entry(which_frame, justify="right", width=8) self.end_entry.insert("end", str(end_value)) self.end_entry.grid(row=row_number, column=2) self.end_entry.config(state="disabled") #Delta Checkbox self.delta_check = IntVar() self.delta_check.set(1) self.delta_button = Checkbutton( which_frame, text="Delta Method", variable=self.delta_check, command=self.delta_button_toggle) self.delta_button.grid(row=row_number, column=3) #Delta Value self.delta = Entry(which_frame, justify="right", width=8) self.delta.insert("end", '0') self.delta.grid(row=row_number, column=4) #Smooth Start Checkbox self.smooth_start_check = IntVar() self.smooth_start_check.set(1) self.smooth_start_button = Checkbutton( which_frame, text="Smooth Start", variable=self.smooth_start_check) self.smooth_start_button.grid(row=row_number, column=5) self.smooth_start_button.config(state="disabled") #Smooth End Checkbox self.smooth_end_check = IntVar() self.smooth_end_check.set(1) self.smooth_end_button = Checkbutton( which_frame, text="Smooth End", variable=self.smooth_end_check) self.smooth_end_button.grid(row=row_number, column=6) self.smooth_end_button.config(state="disabled") #Cycle Checkbox self.cycle_check = IntVar() self.cycle_check.set(0) self.cycle_button = Checkbutton( which_frame, text="Cycle", variable=self.cycle_check, command=self.cycle_button_toggle) self.cycle_button.grid(row=row_number, column=7) #Cycle Period self.cycle_period = Entry(which_frame, justify="right", width=8) self.cycle_period.insert("end", '120') self.cycle_period.grid(row=row_number, column=8) self.cycle_period.config(state="disabled") return def delta_button_toggle(self, event=None): checked = self.delta_check.get() if self.cycle_check.get() == self.delta_check.get() == 1: self.cycle_button.invoke() if checked: self.delta.config(state=NORMAL) self.end_entry.config(state="disabled") self.smooth_start_check.set(0) self.smooth_end_check.set(0) self.smooth_start_button.config(state="disabled") self.smooth_end_button.config(state="disabled") else: self.delta.config(state="disabled") self.end_entry.config(state=NORMAL) if self.cycle_check.get() == 0: self.smooth_start_button.config(state=NORMAL) self.smooth_end_button.config(state=NORMAL) def cycle_button_toggle(self, event=None): checked = self.cycle_check.get() if self.cycle_check.get() == self.delta_check.get() == 1: self.delta_button.invoke() if checked: self.cycle_period.config(state=NORMAL) self.end_entry.config(state=NORMAL) self.smooth_start_check.set(0) self.smooth_end_check.set(0) self.smooth_start_button.config(state="disabled") self.smooth_end_button.config(state="disabled") else: self.cycle_period.config(state="disabled") if self.delta_check.get() == 0: self.smooth_start_button.config(state=NORMAL) self.smooth_end_button.config(state=NORMAL) self.end_entry.config(state=NORMAL)
def __init__(self, master, title, x_coor, y_coor, data, variant=False, font_size=11): self.__chb_var = IntVar() self.__state = StringVar() self.__count = StringVar() self.__xObs = StringVar() self.__p_value = StringVar() self.__result = StringVar() self.__results = [] self.__variant = variant checkbox = Checkbutton(master, text=title, variable=self.__chb_var) checkbox.config(font=("Calibri", font_size)) checkbox.place(x=x_coor, y=y_coor) state_label = LabelTag(master, 'State', (x_coor + 60), (y_coor + 30), width=100, font_size=font_size, border=2, relief='groove') if variant: self.__state.set('-1.0') else: self.__state.set('+1') state_option = OptionMenu(master, self.__state, *data) state_option.place(x=(x_coor + 60), y=(y_coor + 60), height=25, width=100) if not variant: xObs_label = LabelTag(master, 'CHI-SQUARED', (x_coor + 165), (y_coor + 30), width=350, font_size=font_size, border=2, relief='groove') xObs_Entry = Entry(master, textvariable=self.__xObs) xObs_Entry.place(x=(x_coor + 165), y=(y_coor + 60), width=350, height=25) else: count_label = LabelTag(master, 'Count', (x_coor + 165), (y_coor + 30), width=350, font_size=font_size, border=2, relief='groove') count_Entry = Entry(master, textvariable=self.__count) count_Entry.place(x=(x_coor + 165), y=(y_coor + 60), width=350, height=25) pass p_value_label = LabelTag(master, 'P-Value', (x_coor + 520), (y_coor + 30), width=350, font_size=font_size, border=2, relief='groove') p_value_Entry = Entry(master, textvariable=self.__p_value) p_value_Entry.place(x=(x_coor + 520), y=(y_coor + 60), width=350, height=25) conclusion_label = LabelTag(master, 'Conclusion', (x_coor + 875), (y_coor + 30), width=150, font_size=font_size, border=2, relief='groove') conclusion_Entry = Entry(master, textvariable=self.__result) conclusion_Entry.place(x=(x_coor + 875), y=(y_coor + 60), width=150, height=25) update_button = Button(master, text='Update', command=self.update) update_button.config(font=("Calibri", 10)) update_button.place(x=(x_coor + 1030), y=(y_coor + 60), width=180, height=25)
class MainWindow: def __init__(self): global root self.provider = None self.session = None self.show_image = False self.original_image = None self.original_image_name = None self.main_image = None self.main_image_orig = None self.resized = False self.thumb_prefix = None self.proxies = None self.gallery_url = None self.hist_stack = [] self.fwd_stack = [] self.interrupt = False self.thumb_url = None self.image_url = None self.menu_bar = Menu(root) self.menu_bar.add_command(label="<< Back", command=self.back_in_history) self.menu_bar.add_command(label="Forward >>", command=self.forward_in_history) self.menu_bar.add_command(label="View gallery", command=self.view_gallery_url) self.menu_bar.add_command(label="Cancel", command=self.calcel) root.config(menu=self.menu_bar) frm_top = Frame(root) self.frm_main = ScrollFrame(root) frm_status = Frame(root) frm_center = Frame(self.frm_main.view_port) frm_left = Frame(self.frm_main.view_port) frm_right = Frame(self.frm_main.view_port) frm_caption = Frame(frm_center) frm_image = Frame(frm_center) self.btn_prev = LinkButton(self, frm_caption, text="Previous") self.btn_prev.link = "prev link" self.btn_prev.pack(side=LEFT) self.btn_save = Button(frm_caption, text="Save", command=self.save_image) self.btn_save.pack(side=LEFT) self.btn_next = LinkButton(self, frm_caption, text="Next") self.btn_next.link = "next link" self.btn_next.pack(side=LEFT) self.btn_paste = Button(frm_top, text="Paste", command=self.paste_from_clipboard) self.btn_paste.pack(side=LEFT) self.btn_update = Button(frm_top, text="Load image", command=self.load_image_from_input) self.btn_update.pack(side=LEFT) self.sv_url = StringVar() self.entry_url = Entry(frm_top, textvariable=self.sv_url, width=100) self.entry_url.bind("<FocusIn>", self.focus_callback) self.entry_url.bind('<Return>', self.enter_callback) self.entry_url.pack(side=LEFT) self.use_proxy = BooleanVar() self.use_proxy.set(False) self.use_proxy.trace('w', self.on_use_proxy_change) self.chk_use_proxy = Checkbutton(frm_top, text='Use proxy', variable=self.use_proxy) self.chk_use_proxy.pack(side=LEFT) self.sv_proxy = StringVar() self.entry_proxy = Entry(frm_top, textvariable=self.sv_proxy, width=30, state=DISABLED) self.entry_proxy.pack(side=LEFT) self.btn_force = Button(frm_top, text="Force load", command=self.force_load_image) self.btn_force.pack(side=LEFT) try: with open("proxy.txt") as f: self.sv_proxy.set(f.readline().strip()) except BaseException as error: print(error) traceback.print_exc() self.btn_image = Button(frm_image, command=self.resize_image) self.btn_image.bind("<Button-3>", self.load_original_image_in_thread) self.btn_image.pack() self.left_buttons = self.fill_panel(frm_left) self.right_buttons = self.fill_panel(frm_right) self.status = StringVar() self.status_label = Label(frm_status, bd=1, relief=SUNKEN, anchor=W, textvariable=self.status) self.status_label.pack(side=LEFT, fill=BOTH, expand=1) self.status.set('Status Bar') self.progress_bar = ttk.Progressbar(frm_status, orient=HORIZONTAL, length=200, mode='indeterminate') root.bind("<FocusIn>", self.focus_callback) root.bind("<BackSpace>", self.backspace_callback) root.bind("<space>", self.space_callback) root.protocol("WM_DELETE_WINDOW", self.on_close) frm_caption.pack() frm_image.pack() frm_left.pack(side=LEFT, fill=BOTH, expand=1) frm_center.pack(side=LEFT) frm_right.pack(side=RIGHT, fill=BOTH, expand=1) frm_top.pack() self.frm_main.pack(fill=BOTH, expand=1) frm_status.pack(fill=X) self.hist_logger = logging.getLogger('history') self.hist_logger.setLevel(logging.INFO) self.fh_hist = logging.FileHandler( os.path.join(LOGS, f'hist_{int(time.time())}.log')) self.fh_hist.setLevel(logging.INFO) self.hist_logger.addHandler(self.fh_hist) def force_load_image(self): self.load_page_in_thread(self.sv_url.get().strip(), True, True) def load_image_from_input(self): self.load_page_in_thread(self.sv_url.get().strip()) def load_page_in_thread(self, input_url, remember=True, ignore_cache=False): self.set_controls_state(DISABLED) self.interrupt = False future = executor.submit(self.load_image_retry, input_url, remember, ignore_cache) future.add_done_callback(lambda f: self.set_controls_state(NORMAL)) def load_image_retry(self, input_url, remember, ignore_cache): global root try: err_count = 0 while err_count < MAX_ERRORS: root.after_idle(self.set_undefined_state) if self.load_image(input_url, remember, ignore_cache): break if self.interrupt: break err_count += 1 except BaseException as error: print("Exception URL: " + input_url) print(error) traceback.print_exc() def load_image(self, input_url, remember, ignore_cache): global root if len(input_url) == 0: return False root.after_idle(self.sv_url.set, input_url) self.provider = self.get_provider() if self.provider is None: return False cache_path = os.path.join(CACHE, self.provider.get_domen()) if not os.path.exists(cache_path): os.mkdir(cache_path) proxy = self.sv_proxy.get().strip() if self.use_proxy.get() and len(proxy.strip()) > 0: self.proxies = { "http": "http://" + proxy, "https": "https://" + proxy } with open("proxy.txt", "w") as f: f.write(proxy) else: self.proxies = None http_session = requests.Session() http_session.headers.update(HEADERS) ident = self.get_id(input_url) if ident is None: print("ident is None") return False input_url = "https://" + self.provider.get_host() + "/" + ident root.after_idle(root.title, input_url) try: html = self.get_from_cache(ident) if ignore_cache or (html is None) or (len(html) == 0): html = self.get_final_page(ident, input_url, http_session) if (html is None) or (len(html) == 0): return False html = html.decode('utf-8') if not self.render_page(ident, html, http_session): return False if remember and (input_url is not None): if len(self.hist_stack) == 0 or (input_url != self.hist_stack[-1]): self.hist_stack.append(input_url) self.hist_logger.info(f'{input_url}\t{self.thumb_url}') if len(self.fwd_stack) > 0 and (input_url == self.fwd_stack[-1]): self.fwd_stack.pop() else: self.fwd_stack.clear() except BaseException as error: print("Exception URL: " + input_url) print(error) traceback.print_exc() return False finally: http_session.close() return True def get_final_page(self, ident, input_url, http_session): global root response = http_session.get(input_url, proxies=self.proxies, timeout=TIMEOUT) if response.status_code == 404: print("input_url response.status_code == 404") return None html = response.content.decode('utf-8') if DEBUG: with open('1.html', 'w') as f: f.write(html) # sometimes this functions fails (i don't want to tamper with this) redirect_url = self.provider.get_redirect_url(html) if redirect_url is not None: if len(redirect_url) == 0: print("(redirect_url is None) or (len(redirect_url) == 0)") return None http_session.headers.update({'Referer': input_url}) response = http_session.get(redirect_url, proxies=self.proxies, timeout=TIMEOUT) if response.status_code == 404: print("redirect_url response.status_code == 404") return None html = response.content.decode('utf-8') if DEBUG: with open('2.html', 'w') as f: f.write(html) pos = html.find('File Not Found') if pos >= 0: print("File Not Found: " + input_url) return None param = self.provider.get_post_param(html) if len(param) == 0: print("len(param) == 0") return None post_fields = {'op': 'view', 'id': ident, 'pre': 1, param: 1} response = http_session.post(redirect_url, data=post_fields, proxies=self.proxies, timeout=TIMEOUT) if response.status_code == 404: print("POST: redirect_url response.status_code == 404") return None html = response.content if DEBUG: with open('3.html', 'wb') as f: f.write(html) self.put_to_cache(ident, html) return html def render_page(self, ident, html, http_session): self.thumb_url = get_thumb(html) if (self.thumb_url is None) or (len(self.thumb_url) == 0): print("len(thumb_url) == 0") return False slash_pos = self.thumb_url.rfind('/') self.thumb_prefix = self.thumb_url[:slash_pos + 1] thumb_filename = self.thumb_url[slash_pos + 1:] dot_pos = thumb_filename.rfind('.') thumb_filename = thumb_filename[:dot_pos] self.gallery_url = search('href="([^"]*)">More from gallery</a>', html) self.reconfigure_prev_button(http_session, html) self.reconfigure_next_button(http_session, html) executor.submit(self.reconfigure_left_buttons, html) executor.submit(self.reconfigure_right_buttons, html) self.image_url = self.provider.get_image_url(html) fname = get_filename(self.image_url) dot_pos = fname.rfind('.') self.original_image_name = fname[:dot_pos] + '_' + ident self.original_image = self.get_from_cache(self.original_image_name) bg_color = 'green' self.resized = True if (self.original_image is None) or (len(self.original_image) == 0): self.original_image = self.get_from_cache(thumb_filename) self.resized = False if (self.original_image is None) or (len(self.original_image) == 0): response = http_session.get(self.thumb_url, proxies=self.proxies, timeout=TIMEOUT) if response.status_code == 404: print("image_url response.status_code == 404") return False self.original_image = response.content # if DEBUG: # with open(self.original_image_name, 'wb') as f: # f.write(self.original_image) self.put_to_cache(thumb_filename, self.original_image) bg_color = 'red' self.resized = False img = Image.open(io.BytesIO(self.original_image)) w, h = img.size k = MAIN_IMG_WIDTH / w img_resized = img.resize((MAIN_IMG_WIDTH, int(h * k))) root.after_idle(root.title, f"{root.title()} ({w}x{h})") self.main_image_orig = ImageTk.PhotoImage(img) self.main_image = ImageTk.PhotoImage(img_resized) photo_image = self.main_image if self.resized else self.main_image_orig root.after_idle(self.btn_image.config, { 'image': photo_image, 'background': bg_color }) if os.path.exists(os.path.join(OUTPUT, self.original_image_name)): root.after_idle(self.btn_save.config, {'background': 'green'}) return True def focus_callback(self, event): self.entry_url.selection_range(0, END) def enter_callback(self, event): self.load_image_from_input() def backspace_callback(self, event): self.back_in_history() def space_callback(self, event): self.forward_in_history() def on_close(self): global root root.update_idletasks() root.destroy() self.fh_hist.close() self.hist_logger.removeHandler(self.fh_hist) def calcel(self): self.interrupt = True def set_undefined_state(self): global root self.main_image = None self.main_image_orig = None self.original_image = None self.original_image_name = None self.btn_image.config(image='', background="SystemButtonFace") self.btn_save.config(background="SystemButtonFace") root.title(None) self.btn_prev.reset() self.btn_next.reset() for btn in self.left_buttons: btn.reset() for btn in self.right_buttons: btn.reset() self.frm_main.scroll_top_left() def paste_from_clipboard(self): self.sv_url.set(clipboard.paste()) self.entry_url.selection_range(0, END) def save_image(self): if self.original_image is None: return filename = self.original_image_name i = 1 while os.path.exists(os.path.join(OUTPUT, filename)): filename = f'{self.original_image_name}_{i:04}' i += 1 with open(os.path.join(OUTPUT, filename), 'wb') as f: f.write(self.original_image) self.btn_save.config(background="green") def on_enter(self, event): self.status.set(event.widget.link) def on_leave(self, enter): self.status.set("") def fill_panel(self, panel): buttons = [] for i in range(4): Grid.columnconfigure(panel, i, weight=1) for j in range(2): Grid.rowconfigure(panel, j, weight=1) btn = LinkButton(self, panel, text=f"({i}, {j})") btn.link = None btn.grid(row=i, column=j, sticky=NSEW, padx=PAD, pady=PAD) buttons.append(btn) return buttons def resize_image(self): self.btn_image.config( image=(self.main_image_orig if self.resized else self.main_image)) self.resized = not self.resized self.frm_main.scroll_top_left() def get_id(self, url): found = re.search( r"https?://" + self.provider.get_domen() + r"\.[a-z]+/(.+?)(?:/|$)", url) if (found is None) or (found.group(0) is None): return None return found.group(1) def reconfigure_left_buttons(self, html): tab = get_more_from_author(html) self.reconfigure_buttons(self.left_buttons, tab) def reconfigure_right_buttons(self, html): tab = get_more_from_gallery(html) self.reconfigure_buttons(self.right_buttons, tab) def reconfigure_prev_button(self, http_session, html): url = get_prev_url(html) if len(url) == 0: return ident = self.get_id(url) img_url = self.thumb_prefix + ident + '_t.jpg' self.reconfigure_button(http_session, self.btn_prev, url, img_url) def reconfigure_next_button(self, http_session, html): url = get_next_url(html) if len(url) == 0: return ident = self.get_id(url) img_url = self.thumb_prefix + ident + '_t.jpg' self.reconfigure_button(http_session, self.btn_next, url, img_url) def reconfigure_button(self, http_session, btn, url, img_url): global root filename = get_filename(img_url) dot_pos = filename.rfind('.') filename = filename[:dot_pos] bg_color = "green" image = self.get_from_cache(filename) if (image is None) or (len(image) == 0): image = download_image(http_session, img_url) self.put_to_cache(filename, image) bg_color = "red" if (image is None) or (len(image) == 0): return img = Image.open(io.BytesIO(image)) w, h = img.size k = IMG_WIDTH / w img_resized = img.resize((IMG_WIDTH, int(h * k))) photo_image = ImageTk.PhotoImage(img_resized) if photo_image is None: return root.after_idle(btn.set_values, url, partial(self.load_page_in_thread, url), photo_image, bg_color) def reconfigure_buttons(self, buttons, html): http_session = requests.Session() http_session.headers.update(HEADERS) try: for btn in buttons: btn.reset() i = 0 for m in re.finditer('<td>.*?href="(.*?)".*?src="(.*?)".*?</td>', html, re.MULTILINE | re.DOTALL): self.reconfigure_button(http_session, buttons[i], m.group(1), m.group(2)) i += 1 except BaseException as error: print(error) traceback.print_exc() finally: http_session.close() def on_use_proxy_change(self, *args): if self.use_proxy.get(): self.entry_proxy.config(state=NORMAL) self.entry_proxy.focus_set() self.entry_proxy.selection_range(0, END) else: self.entry_proxy.config(state=DISABLED) def get_provider(self): input_url = self.sv_url.get() pos = input_url.find(ImgRock.DOMEN) if pos >= 0: return ImgRock() pos = input_url.find(ImgView.DOMEN) if pos >= 0: return ImgView() pos = input_url.find(ImgTown.DOMEN) if pos >= 0: return ImgTown() pos = input_url.find(ImgOutlet.DOMEN) if pos >= 0: return ImgOutlet() pos = input_url.find(ImgMaze.DOMEN) if pos >= 0: return ImgMaze() pos = input_url.find(ImgDew.DOMEN) if pos >= 0: return ImgDew() return None def view_gallery_url(self): if (self.gallery_url is None) or (len(self.gallery_url) == 0): return clipboard.copy(self.gallery_url) GalleryWindow(self, Toplevel(root)) def back_in_history(self): if len(self.hist_stack) < 2: return self.fwd_stack.append(self.hist_stack.pop()) self.load_page_in_thread(self.hist_stack[-1], False) def forward_in_history(self): if len(self.fwd_stack) == 0: return self.load_page_in_thread(self.fwd_stack[-1]) def get_from_cache(self, filename): full_path = os.path.join(CACHE, self.provider.get_domen(), filename) if not os.path.exists(full_path): return None mod_time = time.time() os.utime(full_path, (mod_time, mod_time)) with open(full_path, 'rb') as f: return f.read()[::-1] def put_to_cache(self, filename, data): if (data is None) or (len(data) == 0): return full_path = os.path.join(CACHE, self.provider.get_domen(), filename) with open(full_path, 'wb') as f: f.write(data[::-1]) def set_controls_state(self, status): self.btn_prev.config(state=status) self.btn_next.config(state=status) self.btn_update.config(state=status) self.btn_force.config(state=status) self.entry_url.config(state=status) self.btn_paste.config(state=status) self.chk_use_proxy.config(state=status) self.entry_proxy.config(state=status) self.menu_bar.entryconfig("<< Back", state=status) self.menu_bar.entryconfig("Forward >>", state=status) for btn in self.left_buttons: btn.config(state=status) for btn in self.right_buttons: btn.config(state=status) if status == DISABLED: self.progress_bar.pack(side=LEFT) self.progress_bar.start() else: self.progress_bar.pack_forget() self.progress_bar.stop() def load_original_image_in_thread(self, event): executor.submit(self.load_original_image) def load_original_image(self): response = requests.get(self.image_url, proxies=self.proxies, timeout=TIMEOUT) if response.status_code == 404: print("image_url response.status_code == 404") return self.original_image = response.content # if DEBUG: # with open(self.original_image_name, 'wb') as f: # f.write(self.original_image) self.put_to_cache(self.original_image_name, self.original_image) bg_color = 'red' self.resized = True img = Image.open(io.BytesIO(self.original_image)) w, h = img.size k = MAIN_IMG_WIDTH / w img_resized = img.resize((MAIN_IMG_WIDTH, int(h * k))) root.after_idle(root.title, f"{root.title()} ({w}x{h})") self.main_image_orig = ImageTk.PhotoImage(img) self.main_image = ImageTk.PhotoImage(img_resized) root.after_idle(self.btn_image.config, { 'image': self.main_image, 'background': bg_color })
class User_Interface: def __init__(self, master): self.df = pd.read_csv ('diabetes.csv') #intialising empty arrays to store data results #testing/training self.x_train = [] self.x_test = [] self.y_test = [] self.y_train = [] self.master = master self.master.title('Diabetes Classification') self.master.config(background = 'light grey') self.master.geometry("800x650+30+30") self.create_window(master) def create_window(self, master): #===============Data Analysis Danvas========== self.canvas = Canvas(self.master, height= 180, width=380, background = 'light grey',borderwidth=1, relief=GROOVE) self.canvas.place(x=10, y=20) self.listbox = Listbox(self.master, height = 9, width = 15) self.listbox.place(x=40, y=40) self.title= Label(self.master, text='Data Analysis', background='light grey') self.title.place(x=40,y=20) self.title.config(font=('System', 10)) #split data button self.load_button= Button(self.master, text='Split Data') self.load_button.place(x=230, y=160) self.load_button.config(background= 'light grey', activebackground= 'grey', command= self.preprocessing) #Data Ananysis text boxese self.class_type = Entry(self.master, width= 10) self.class_type.place(x=280, y=40) self.class_typel = Label(self.master, text='DataSet Class Labels', background= 'light grey') self.class_typel.place(x=160, y=40) self.class_typel.config(font=('Times', 9)) self.class_typel2 = Label(self.master, text='Count of Data Items', background= 'light grey') self.class_typel2.place(x=160, y=60) self.class_typel2.config(font=('Times', 9)) self.class_type2 = Entry(self.master, width= 10) self.class_type2.place(x=280, y=60) self.test_datat= Entry(self.master, width=10) self.test_datat.place(x=280, y=80) self.test_data= Label(self.master, text='Testing Data Items', background='light grey') self.test_data.place(x=160, y=80) self.test_data.config(font=('Times', 9)) self.train_datat= Entry(self.master, width=10) self.train_datat.place(x=280, y=100) self.train_data= Label(self.master, text='Training Data Items', background='light grey') self.train_data.place(x=160, y=100) self.train_data.configure(font=('Times', 9)) #==============KNN Canas===================== self.canvas_1 = Canvas(self.master, height= 180, width=380, background = 'light grey',borderwidth=1, relief=GROOVE) self.canvas_1.place(x=405, y=20) self.title= Label(self.master, text='K Nearest Neighbor', background='light grey') self.title.place(x=440,y=20) self.title.config(font=('System', 10)) #knn checkboxes and labels self.train_l = Label(self.master, text= 'Enter K', background='light grey') self.train_l.place(x=440, y=40) self.train_l.config(font=('Times', 9)) self.train_l = Entry(self.master, width= 10) self.train_l.place(x=500, y=40) self.train2 = Label(self.master, text='Train knn without Analysis', background='light grey') self.train2.place(x=440, y=60) self.train2.config(font=('Times', 9)) self.var = IntVar() self.train2 = Checkbutton(self.master, background='light grey', variable = self.var) self.train2.place(x=660, y=60) self.train_l2 = Label(self.master, text='Train with Principal Component Analysis', background='light grey') self.train_l2.place(x=440, y=80) self.train_l2.config(font=('Times', 9)) self.var1 = IntVar() self.train_l2 = Checkbutton(self.master, background='light grey', variable = self.var1) self.train_l2.place(x=660, y=80) self.train_l3 = Label(self.master, text='Train with Linear Discriminant Analysis', background='light grey') self.train_l3.place(x=440, y=100) self.train_l3.config(font=('Times', 9)) self.var2 = IntVar() self.train_l3 = Checkbutton(self.master, background='light grey', variable = self.var2) self.train_l3.place(x=660, y=100) #knn button self.kb= Button(self.master, text='Train') self.kb.place(x=560, y=160) self.kb.config(background= 'light grey', activebackground= 'grey', command= self.knn_checked) #==============Naive Bayes=================== self.canvas_2 = Canvas(self.master, height= 180, width=380, background = 'light grey',borderwidth=1, relief=GROOVE) self.canvas_2.place(x=10, y=220) self.ntitle= Label(self.master, text='Naive Bayes', background='light grey') self.ntitle.place(x=40,y=220) self.ntitle.config(font=('System', 10)) #naive bayes checkboxes and labels self.ntrain_l = Label(self.master, text='Train without Analysis', background='light grey') self.ntrain_l.place(x=40, y=260) self.ntrain_l.config(font=('Times', 9)) self.var3 = IntVar() self.ntrain_l = Checkbutton(self.master, background='light grey', variable = self.var3) self.ntrain_l.place(x=260, y=260) self.ntrain_l2 = Label(self.master, text='Train with Principal Component Analysis', background='light grey') self.ntrain_l2.place(x=40, y=280) self.ntrain_l2.config(font=('Times', 9)) self.var4 = IntVar() self.ntrain_l2 = Checkbutton(self.master, background='light grey', variable = self.var4) self.ntrain_l2.place(x=260, y=280) self.ntrain_l3 = Label(self.master, text='Train with Linear Discriminant Analysis', background='light grey') self.ntrain_l3.place(x=40, y=300) self.ntrain_l3.config(font=('Times', 9)) self.var5 = IntVar() self.ntrain_l3 = Checkbutton(self.master, background='light grey', variable = self.var5) self.ntrain_l3.place(x=260, y=300) #Niave Bayes train button self.nb= Button(self.master, text='Train') self.nb.place(x=160, y=360) self.nb.config(background= 'light grey', activebackground= 'grey', command= self.nb_checked) #=============Neaural Network Canvas============ self.canvas_3 = Canvas(self.master, height= 180, width=380, background = 'light grey',borderwidth=1, relief=GROOVE) self.canvas_3.place(x=405, y=220) self.nntitle= Label(self.master, text='Neural Network', background='light grey') self.nntitle.place(x=440,y=220) self.nntitle.config(font=('System', 10)) #neaural network checkboxes and labels self.nntrain_l = Label(self.master, text='Train without Analysis', background='light grey') self.nntrain_l.place(x=440, y=260) self.nntrain_l.config(font=('Times', 9)) self.var6 = IntVar() self.nntrain_l = Checkbutton(self.master, background='light grey', variable= self.var6) self.nntrain_l.place(x=660, y=260) self.nntrain_l2 = Label(self.master, text='Train with Principal Component Analysis', background='light grey') self.nntrain_l2.place(x=440, y=280) self.nntrain_l2.config(font=('Times', 9)) self.var7 = IntVar() self.nntrain_l2 = Checkbutton(self.master, background='light grey', variable=self.var7) self.nntrain_l2.place(x=660, y=280) self.nntrain_l3 = Label(self.master, text='Train with Linear Discriminant Analysis', background='light grey') self.nntrain_l3.place(x=440, y=300) self.nntrain_l3.config(font=('Times', 9)) self.var8 = IntVar() self.nntrain_l3 = Checkbutton(self.master, background='light grey', variable=self.var8) self.nntrain_l3.place(x=660, y=300) #neaural network button self.nn= Button(self.master, text='Train', command = self.mlp_checked) self.nn.place(x=570, y=360) self.nn.config(background= 'light grey', activebackground= 'grey', ) #=============Classification Results Canvas====================== self.canvas_4 = Canvas(self.master, height= 230, width=780, background = 'gray68',borderwidth=1, relief=SUNKEN) self.canvas_4.place(x=10, y=410) self.rtitle= Label(self.master, text='Classification Report', background='gray68') self.rtitle.place(x=20, y=420) self.rtitle.config(font=('System', 10)) #classification results text boxes self.class_accl= Label(self.master, text='Accuracy', background='gray68') self.class_accl.place(x=20, y=470) self.class_accl.configure(font=('Times', 9)) self.class_acc = Entry(self.master, width= 10) self.class_acc.place(x=180, y=470) self.class_sens= Label(self.master, text= 'Sensitivity', background='gray68') self.class_sens.configure(font=('Times', 9)) self.class_sens.place(x=20, y=500) self.class_sense= Entry(self.master, width=10) self.class_sense.place(x=180, y=500) self.class_spec= Label(self.master, text= 'Specificity', background='gray68') self.class_spec.configure(font=('Times', 9)) self.class_spec.place(x=20, y=530) self.class_spece= Entry(self.master, width=10) self.class_spece.place(x=180, y=530) self.rocl = Label(self.master, text= 'ROC/AUC Score', background='gray68') self.rocl.configure(font=('Times', 9)) self.rocl.place(x=20, y=560) self.rocscore = Entry(self.master, width=10) self.rocscore.place(x=180, y=560) #auc-roc curve canvas self.canvas_im = Canvas(self.master, height= 210, width=260, background = 'gray68',borderwidth=1, relief=SUNKEN) self.canvas_im.pack() self.canvas_im.place(x=250, y=420) self.canvas_iml= Label(self.master, text='AUC-ROC Curve', background='white',borderwidth=1, relief=SUNKEN) self.canvas_iml.place(x=340, y=612) self.canvas_iml.configure(font=('Times', 8)) #scatter graph canvas self.canvas_im2 = Canvas(self.master, height= 210, width=260, background = 'gray68',borderwidth=1, relief=SUNKEN) self.canvas_im2.pack() self.canvas_im2.place(x=520, y=420) self.canvas_im2l= Label(self.master, text='X=PCA=1 Y=PCA=2', background='white',borderwidth=1, relief=SUNKEN) self.canvas_im2l.place(x=600, y=612) self.canvas_im2l.configure(font=('Times', 9)) #listbox and textboxes for data analysis when split data is clicked def clear_dataset(self): self.listbox.delete(0,"end") self.class_type.delete(0,"end") self.class_type2.delete(0,"end") #load diabetes dataset into listbox and data feilds when split data has been clicked def open_file(self): self.clear_dataset() data_class = self.df.iloc[:,-1] d_class = data_class.unique() d_count = data_class.count() #insert target feature into entry box self.class_type.insert("end", d_class) #insert count of data items into entry box self.class_type2.insert("end", d_count) data_list = list(self.df) #for everyitem/column in datalist for items in data_list: #insert colomns into listbox self.listbox.insert("end", items) #preparing the data before classification def preprocessing(self): self.clear_results() #outcome colomn with all rows x = self.df.drop('Outcome', 1) #just outcome column y = self.df['Outcome'] #split training set 75% test set 25% self.x_train,self.x_test,self.y_train,self.y_test = train_test_split(x, y, test_size=0.25, random_state=0) train_set = len(self.x_train + self.y_train) test_set = len(self.x_test + self.y_test) #add testing and traing data into text boxs self.test_datat.insert("end", test_set) self.train_datat.insert("end", train_set) scaler = MinMaxScaler() self.x_train = scaler.fit_transform(self.x_train) self.x_test = scaler.transform(self.x_test) #add two components scatter graph self.img2=img2 =ImageTk.PhotoImage(Image.open("pca_scatter.png")) self.canvas_im2.create_image(0,0,anchor = "nw", image=img2) #--------------CheckBoxes------------------------------------------------- #show all classifier roc-auc results in canvas def knn_checked(self): #get if checked var = self.var.get() var1 = self.var1.get() var2 = self.var2.get() self.clear_checked() self.canvas_im.delete("all") #if knn without analysis is checked then show knn roc curve if var ==1: self.knn_own() self.img=img =ImageTk.PhotoImage(Image.open("knn_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) #if pca knn is checked then show knn with pca roc curve if var1 == 1: self.knn_pca() self.img=img =ImageTk.PhotoImage(Image.open("pk_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) #if lda knn is checked then show knn with lda roc curve if var2 == 1: self.knn_lda() self.img=img =ImageTk.PhotoImage(Image.open("ldak_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) def nb_checked(self): var3 = self.var3.get() var4 = self.var4.get() var5 = self.var5.get() self.clear_checked() self.canvas_im.delete("all") #if naive bayes without analysis is checked then show naive bayes roc curve if var3 == 1: self.naive_bayes() self.img=img =ImageTk.PhotoImage(Image.open("nb_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) #if naive bayes with pca is cheked then show naive bayes with pca roc curve if var4 == 1: self.naiveb_pca() self.img=img =ImageTk.PhotoImage(Image.open("pcanb_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) #if naive bayes with lda is checked then show naive bayes with lda roc curve if var5 == 1: self.naiveb_lda() self.img=img =ImageTk.PhotoImage(Image.open("ldanb_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) def mlp_checked(self): var6 = self.var6.get() var7 = self.var7.get() var8 = self.var8.get() self.clear_checked() self.canvas_im.delete("all") if var6 ==1: self.mlp() #''change image to knn without pca self.img=img =ImageTk.PhotoImage(Image.open("mlp_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) if var7 == 1: self.mlp_pca() self.img=img =ImageTk.PhotoImage(Image.open("pcamlp_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) if var8 == 1: self.mlp_lda() self.img=img =ImageTk.PhotoImage(Image.open("ldamlp_img.png")) self.canvas_im.create_image(0,0,anchor = "nw", image=img) #clear all checked button once clicked def clear_checked(self): self.var.set(0) self.var1.set(0) self.var2.set(0) self.var3.set(0) self.var4.set(0) self.var5.set(0) self.var6.set(0) self.var7.set(0) self.var8.set(0) #------------------end of checkboxes----------------------------------------- #linear discriminent analysis with one component on training data def lda(self): lda = LDA(n_components=1) self.xlda_train = lda.fit_transform(self.x_train, self.y_train) self.xlda_test = lda.transform(self.x_test) return self.xlda_test, self.xlda_train #principle component anaysis with seven components tested to give best results def pca(self): pca = PCA(n_components=7) self.xpca_train = pca.fit_transform(self.x_train) self.xpca_test = pca.transform(self.x_test) return self.xpca_test, self.xpca_train #retrive all results for classification report def get_results(self, x, y): self.acc =accuracy_score(self.y_test, x) #seperate confusion matrix to get true negative, flase positive, false negative and true #true positive for specificity result tn, fp, fn, tp = confusion_matrix(self.y_test, x).ravel() self.spec = tn / (tn+fp) self.roc_score =roc_auc_score(self.y_test, y) self.sens = recall_score(self.y_test, x) #===========================Classifiers============================================= #three different classifiers for each model one train without ananysis then pca and lda #call methods for training/ splitting and standardisation of data #fit all classifiers with training data #clear all classification results once a classifier has been trained # insert the new classifier resutls into classification report text boxes #-------------------------KNN-------------------------------------------- def k_n_n(self, x, y): #get input value r = int(self.train_l.get()) #classify knn with input valaue for n_neighbors testing #differnt k values correct k = 11 knn = KNeighborsClassifier(n_neighbors=r) knn.fit(x,self.y_train) self.y_pred = knn.predict(y) self.y_score = knn.predict_proba(y)[:,1] return self.y_pred, self.y_score #knn withou anaylisis def knn_own(self): self.clear_results() self.preprocessing() self.k_n_n(self.x_train, self.x_test) self.get_results(self.y_pred, self.y_score) self.get_results(self.y_pred, self.y_score) self.insert_results() #knn with linear discriminent analysis def knn_lda(self): self.clear_results() self.preprocessing() self.lda() self.k_n_n(self.xlda_train, self.xlda_test) self.get_results(self.y_pred, self.y_score) self.insert_results() #knn with principle component analysis def knn_pca(self): self.clear_results() self.preprocessing() self.pca() self.k_n_n(self.xpca_train, self.xpca_test) self.get_results(self.y_pred, self.y_score) self.insert_results() #-------------------------Naive Bayes---------------------------------------- #train naive bayes def n_b(self, x, y): clf = GaussianNB() clf.fit(x, self.y_train) self.yn_pred = clf.predict(y) self.yn_scores = clf.predict_proba(y)[:,1] return self.yn_pred, self.yn_scores #naive bayes without anaylis def naive_bayes(self): self.clear_results() self.preprocessing() self.n_b(self.x_train, self.x_test) self.get_results(self.yn_pred, self.yn_scores) self.insert_results() #naive bayes with linear discriminent anaylsis def naiveb_lda(self): self.clear_results() self.preprocessing() self.lda() self.n_b(self.xlda_train, self.xlda_test) self.get_results(self.yn_pred, self.yn_scores) self.insert_results() #naive bayes with principle component anaylsis def naiveb_pca(self): self.clear_results() self.preprocessing() self.pca() self.n_b(self.xpca_train, self.xpca_test) self.get_results(self.yn_pred, self.yn_scores) self.insert_results() #---------------------MultiLayer Perceptron------------------------------------ #MultiLayer Perceptron method with 100 iterations and ten hidden layers for three nodes def m_l_p(self, x, y): mlp = MLPClassifier(hidden_layer_sizes=(10,10,10), max_iter=1000, random_state=1) mlp.fit(x, self.y_train) self.ym_pred = mlp.predict(y) self.ym_scores = mlp.predict_proba(y)[:,1] return self.ym_pred, self.ym_scores #empty contents train multilayer perceptron with Principle component Analysis #intilize methods def mlp(self): self.clear_results() self.preprocessing() self.m_l_p(self.x_train, self.x_test) self.get_results(self.ym_pred, self.ym_scores) self.insert_results() def mlp_lda(self): self.clear_results() self.preprocessing() self.lda() self.m_l_p(self.xlda_train, self.xlda_test) self.get_results(self.ym_pred, self.ym_scores) self.insert_results() def mlp_pca(self): self.clear_results() self.preprocessing() self.pca() self.m_l_p(self.xpca_train, self.xpca_test) self.get_results(self.ym_pred, self.ym_scores) self.insert_results() def insert_results(self): #insert all results into text boxes in class report #round results to two decimal places self.class_acc.insert("end",self.acc.round(2)) self.class_sense.insert("end", self.sens.round(2)) self.class_spece.insert("end", self.spec.round(2)) self.rocscore.insert("end", self.roc_score.round(2)) #clear all results in classification report once another #classifier has been selected def clear_results(self): self.test_datat.delete(0,"end") self.class_acc.delete(0,"end") self.train_datat.delete(0,"end") self.class_sense.delete(0, "end") self.class_spece.delete(0, "end") self.rocscore.delete(0,"end")
class Application(Frame): def __init__(self, master=None): """ Main GUI.""" Frame.__init__(self, master) Frame.grid(self, padx=(40, 40), pady=(10, 10)) self.path1 = StringVar() path1_lbl = ttk.Label(self, text='Path:') path1_lbl.grid(column=1, columnspan=4, row=1, sticky=W) path1_entry = ttk.Entry(self, width=30, textvariable=self.path1) path1_entry.grid(column=1, columnspan=4, row=2, sticky=(W, E)) path1_btn = ttk.Button(self, text="Browse", command=self.open1) path1_btn.grid(column=1, row=3, sticky=W, padx=(0, 0)) self.graph1_btn = ttk.Button(self, text="Graph", state=DISABLED, command=lambda: self.graph1(self.C, 1)) self.graph1_btn.grid(column=2, row=3, sticky=W) self.info1_lbl = ttk.Label(self, text='Scan Info/Comments:') self.info1_lbl.grid(column=1, columnspan=4, row=5, sticky=W, pady=(10, 0)) self.info1_Entry = Text(self, width=30, height=12) self.info1_Entry.grid(column=1, columnspan=4, row=6, sticky=(N, W, E)) in_C = StringVar() self.input_entry = ttk.Entry(self, width=10, textvariable=in_C) self.input_entry.grid(column=4, row=3, sticky=(W, E)) self.int_btn = ttk.Button(self, text="Input Array", command=lambda: self.Input_C()) self.int_btn.grid(column=4, row=5, sticky=W) self.int_lbl = ttk.Label(self, text="Inverse Distance " "Weighting Interpolation", font='bold') self.int_lbl.grid(column=1, columnspan=4, row=7, sticky=W, pady=(10, 2)) self.int_btn = ttk.Button(self, text="Interpolate", state=DISABLED, command=lambda: self.interpolation(self.C)) self.int_btn.grid(column=1, row=8, sticky=W) self.NP1 = IntVar() self.NP1.set(5) n_lbl = ttk.Label(self, text='No. pts') n_lbl.grid(column=1, row=9, sticky=(N, W)) self.n_box = Spinbox(self, format='%.0f', from_=0, to=self.NP1.get(), width=5, increment=1) #1E10 self.n_box.grid(column=1, row=10, sticky=(N, W)) self.n_box.insert(1, 5) p_lbl = ttk.Label(self, text='Power') p_lbl.grid(column=2, row=9, sticky=(N, W)) self.p_box = Spinbox(self, format='%.0f', from_=0, to=1E10, width=5, increment=1) self.p_box.grid(column=2, row=10, sticky=(N, W)) self.p_box.insert(1, 2) self.transpose_chk = IntVar() self.trans_btn = Checkbutton(self, text="Tranpose", variable=self.transpose_chk, state=DISABLED, command=lambda: self.check_tr(self.C)) self.trans_btn.grid(column=3, row=10, sticky=(N, W)) self.Refl_x = IntVar() self.Refl_x.set(1) self.Refl_x_btn = Checkbutton(self, text="Reflect_x", variable=self.Refl_x, state=DISABLED, command=lambda: self.check_tr(self.C)) self.Refl_x_btn.grid(column=3, row=9, sticky=(N, W)) self.info1_Entry.insert(END, "Reflect x = %s" % (self.Refl_x.get())) self.N_out_btn = ttk.Button(self, text="Save-Grid", state=DISABLED, command=lambda: self.N_out(self.N)) self.N_out_btn.grid(column=1, row=12, sticky=W) self.M_out_btn = ttk.Button(self, text="Save-xyz", state=DISABLED, command=lambda: self.N_out(self.M)) self.M_out_btn.grid(column=2, row=12, sticky=W) self.plot_btn = ttk.Button(self, text="Plot", state=DISABLED, command=lambda: self.plot(self.C, self.N)) self.plot_btn.grid(column=3, row=12, sticky=(N, W)) # Default values for the interpolated grid self.x01_ = StringVar() self.y01_ = StringVar() self.x01_.set(0.600001) #default self.y01_.set(0.600001) #default self.dx1_ = DoubleVar() # from file self.dy1_ = DoubleVar() # from file self.y02_ = StringVar() self.x02_ = StringVar() self.x02_.set(0.60) #default self.y02_.set(0.60) #default self.dx2_ = StringVar() self.dy2_ = StringVar() self.dx2_.set(0.5) #default self.dy2_.set(0.5) #default self.np_x2_ = StringVar() self.np_y2_ = StringVar() self.np_x2_.set(13) #default self.np_y2_.set(13) #default self.grid2_lbl = ttk.Label(self, text="Interpolated Grid") self.grid2_lbl.grid(column=1, columnspan=4, row=22, sticky=(W, E), pady=(5, 2)) x01_entry = ttk.Entry(self, width=6, textvariable=self.x01_) x01_entry.grid(column=2, row=17, sticky=W) x01_lbl = ttk.Label(self, text='x0') x01_lbl.grid(column=1, row=17, sticky=(N, W), padx=(40, 0)) y01_entry = ttk.Entry(self, width=6, textvariable=self.y01_) y01_entry.grid(column=4, row=17, sticky=W) y01_lbl = ttk.Label(self, text='y0') y01_lbl.grid(column=3, row=17, sticky=(N, W), padx=(40, 0)) dx1_entry = ttk.Entry(self, width=6, textvariable=self.dx1_) dx1_entry.grid(column=2, row=18, sticky=W) dx1_lbl = ttk.Label(self, text='dx1') dx1_lbl.grid(column=1, row=18, sticky=(N, W), padx=(40, 0)) dy1_entry = ttk.Entry(self, width=6, textvariable=self.dy1_) dy1_entry.grid(column=4, row=18, sticky=W) dy1_lbl = ttk.Label(self, text='dy1') dy1_lbl.grid(column=3, row=18, sticky=(N, W), padx=(40, 0)) x02_entry = ttk.Entry(self, width=6, textvariable=self.x02_) x02_entry.grid(column=2, row=23, sticky=W) x02_lbl = ttk.Label(self, text='x0 (Int)') x02_lbl.grid(column=1, row=23, sticky=(N, W), padx=(40, 0)) y02_entry = ttk.Entry(self, width=6, textvariable=self.y02_) y02_entry.grid(column=4, row=23, sticky=W) y02_lbl = ttk.Label(self, text='y0 (Int)') y02_lbl.grid(column=3, row=23, sticky=(N, W), padx=(40, 0)) dx2_entry = ttk.Entry(self, width=6, textvariable=self.dx2_) dx2_entry.grid(column=2, row=24, sticky=W) dx2_lbl = ttk.Label(self, text='dx2') dx2_lbl.grid(column=1, row=24, sticky=(N, W), padx=(40, 0)) dy2_entry = ttk.Entry(self, width=6, textvariable=self.dy2_) dy2_entry.grid(column=4, row=24, sticky=W) dy2_lbl = ttk.Label(self, text='dy2') dy2_lbl.grid(column=3, row=24, sticky=(N, W), padx=(40, 0)) np_x2_entry = ttk.Entry(self, width=6, textvariable=self.np_x2_) np_x2_entry.grid(column=2, row=25, sticky=W) np_x2_lbl = ttk.Label(self, text='np_x2') np_x2_lbl.grid(column=1, row=25, sticky=(N, W), padx=(40, 0)) np_y2_entry = ttk.Entry(self, width=6, textvariable=self.np_y2_) np_y2_entry.grid(column=4, row=25, sticky=W) np_y2_lbl = ttk.Label(self, text='np_y2') np_y2_lbl.grid(column=3, row=25, sticky=(N, W), padx=(40, 0)) self.tipwf = DoubleVar() self.tipwf.set(4220) self.tip = IntVar() self.tip_btn = Checkbutton(self, text="Tip correction (mV)", variable=self.tip, state=DISABLED, command=lambda: self.workfunction(self.C)) self.tip_btn.grid(column=3, columnspan=2, row=26, sticky=(N, W), pady=(15, 0)) self.tip_entry = ttk.Entry(self, width=6, textvariable=self.tipwf) self.tip_entry.grid(column=2, row=26, sticky=E, pady=(15, 0)) minmax_lbl = ttk.Label(self, text='Min and Max x/y') minmax_lbl.grid(column=2, columnspan=3, row=19, sticky=(N, W)) self.xi = IntVar() self.xi.set(0) self.xf = IntVar() self.xf.set(0) xdata_lbl = ttk.Label(self, text='x-data_subset') xdata_lbl.grid(column=1, row=20, sticky=(N, W)) self.xidata_box = Spinbox(self, format='%.0f', from_=0, to=self.xf.get(), width=5, increment=1) self.xidata_box.grid(column=2, row=20, sticky=(N, W), padx=(15, 0)) self.xidata_box.insert(1, 0) self.xfdata_box = Spinbox(self, format='%.0f', from_=0, to=self.xf.get(), width=5, increment=1) self.xfdata_box.grid(column=3, row=20, sticky=(N, W)) self.xfdata_box.insert(1, 0) self.yi = IntVar() self.yi.set(0) self.yf = IntVar() self.yf.set(0) ydata_lbl = ttk.Label(self, text='y-data_subset') ydata_lbl.grid(column=1, row=21, sticky=(N, W)) self.yidata_box = Spinbox(self, format='%.0f', from_=0, to=self.yf.get(), width=5, increment=1) self.yidata_box.grid(column=2, row=21, sticky=(N, W), padx=(15, 0)) self.yidata_box.insert(1, 0) self.yfdata_box = Spinbox(self, format='%.0f', from_=0, to=self.yf.get(), width=5, increment=1) self.yfdata_box.grid(column=3, row=21, sticky=(N, W)) self.yfdata_box.insert(1, 0) def enable_btn(self): self.graph1_btn.config(state='ENABLED') self.int_btn.config(state='ENABLED') self.trans_btn.config(state='normal') self.Refl_x_btn.config(state='normal') self.N_out_btn.config(state='ENABLED') self.M_out_btn.config(state='ENABLED') self.tip_btn.config(state='normal') def Input_C(self): """"Loads tab-delimited data from the corresponding text-box""" A = self.input_entry.get() self.info1_Entry.delete(1.0, END) B = [] reader = csv.reader(A.split('\n'), delimiter='\t') for row in reader: row = row[:] B.append(row) B = B[0:len(B) - 1][0:len(B[0])] for i in range(0, len(B)): for j in range(0, len(B[i])): B[i][j] = float(B[i][j]) B = asarray(B) print(B) self.dx1_.set(0.18) self.dy1_.set(0.18) self.NP1.set(len(B[0]) * len(B) - 1) self.n_box.config(to=self.NP1.get()) self.xf.set(len(B[0])) self.xfdata_box.delete(0, "end") self.xfdata_box.insert(1, self.xf.get()) self.xidata_box.config(to=self.xf.get()) self.xfdata_box.config(to=self.xf.get()) self.yf.set(len(B)) self.yfdata_box.delete(0, "end") self.yfdata_box.insert(1, self.yf.get()) self.yidata_box.config(to=self.yf.get()) self.yfdata_box.config(to=self.yf.get()) self.C = B self.enable_btn() self.graph1(B, 1) return self.C def open1(self): """"Loads data from file and displays footer information""" fileName = filedialog.askopenfilename(title="Open CPD file") try: f = open(fileName, 'r') except IOError: pass i = f.readline().strip() if i == "Work Function data": pass else: i = messagebox.askyesno(title="Open file?", message="CPD file header not present!\n" "Proceed to open file?", default='no') if i == 1: pass else: pass self.path1.set(fileName) g = f.read() f.close() # Only CPD data is loaded but there are other measurements Tracking = g.find('Tracking') Grad = g.find('Grad') # Time = g.find('Time') # User = g.find('User') Footer = g.find('/') - 2 # Footer = Footer - 2 CPD_data = g[0:Tracking] # Tracking_data = g[Tracking:Grad] # Grad_data = g[Grad:Time] # Time_data = g[Time:User] # User_data = g[User:Footer] Footer_data = g[Footer:] a = Footer_data.split("\n") Date = a[0] Grad = [int(i) for i in a[-10].split() if i.isdigit()] DAS_Averages = [int(i) for i in a[-18].split() if i.isdigit()] WF_Averages = [int(i) for i in a[-14].split() if i.isdigit()] Xpoints = [int(i) for i in a[-5].split() if i.isdigit()] Ypoints = [int(i) for i in a[-4].split() if i.isdigit()] Xsteps = [int(i) for i in a[-3].split() if i.isdigit()] Ysteps = [int(i) for i in a[-2].split() if i.isdigit()] Xstepscm = Xsteps[0] * 0.0015 #xyscale Ystepscm = Ysteps[0] * 0.0015 # C is the array used for the raw data C = [] reader = csv.reader(CPD_data.split('\n'), delimiter=',') for row in reader: row = row[:-1] C.append(row) C = C[0:len(C) - 1][0:len(C[0])] for i in range(0, len(C)): for j in range(0, len(C[i])): C[i][j] = float(C[i][j]) C = asarray(C) # Clear the textbox before putting in data for new file self.info1_Entry.delete(1.0, END) info_0 = "%s\n%s\n" % (fileName, Date) info_1 = ("Xpoints = %s\nYpoints = %s\nXsteps = %s (%s cm)\n" "Ysteps= %s (%s cm)" \ % (Xpoints[0], Ypoints[0], Xsteps[0], Xstepscm, Ysteps[0], Ystepscm)) info_2 = "\nDAS_Aves = %s\nWF_Averages = %s\nGrad = %s"\ % (DAS_Averages[0],WF_Averages[0],Grad[0]) self.info1_Entry.insert(END, info_0) self.info1_Entry.insert(END, info_1) self.info1_Entry.insert(END, info_2) if self.Refl_x.get() == 1: info_3 = "\nReflect x = %s" % (self.Refl_x.get()) self.info1_Entry.insert(END, info_3) if self.transpose_chk.get() == 1: info_4 = "\nTranspose = %s" % (self.transpose_chk.get()) self.info1_Entry.insert(END, info_4) self.enable_btn() # To prevent divide by 0 issue 1E-8 is added if Xpoints[0] == len(C[0]): self.dx1_.set(Xstepscm + 1E-8) self.dy1_.set(Ystepscm + 1E-8) else: self.dy1_.set(Xstepscm + 1E-8) self.dx1_.set(Ystepscm + 1E-8) self.NP1.set(len(C[0]) * len(C) - 1) self.n_box.config(to=self.NP1.get()) self.xf.set(len(C[0])) self.xfdata_box.delete(0, "end") self.xfdata_box.insert(1, self.xf.get()) self.xidata_box.config(to=self.xf.get()) self.xfdata_box.config(to=self.xf.get()) self.yf.set(len(C)) self.yfdata_box.delete(0, "end") self.yfdata_box.insert(1, self.yf.get()) self.yidata_box.config(to=self.yf.get()) self.yfdata_box.config(to=self.yf.get()) self.tip.set(0) self.C = C self.Cr = C return self.C, self.Cr def graph1(self, data, row_a): """Graphs the raw CPD data""" plt.close() plt.figure(figsize=(3.5, 3.5), dpi=100, frameon=False) im = plt.imshow(data, cmap='jet') plt.colorbar(im, orientation='vertical', fraction=0.046, pad=0.05) plt.tight_layout() plt.savefig(path.join(tmpdir, im_name1), dpi=100, bbox_inches='tight') c = Canvas(self, width=350, height=350, bg='white') c.grid(row=row_a, column=5, columnspan=2, rowspan=50, sticky=(W, N), padx=50) c.background = PhotoImage(file=path.join(tmpdir, im_name1)) c.create_image(1, 20, image=c.background, anchor=NW) def interpolation(self, C): """Performs inverse distance interpolation""" temp = [] for j in range(int(self.yidata_box.get()), int(self.yfdata_box.get())): temp.append([]) for i in range(int(self.xidata_box.get()), int(self.xfdata_box.get())): temp[j - int(self.yidata_box.get())].append(C[j, i]) # Sub-array of raw data defined by the min and max x/y value C = temp C = asarray(C) n = self.n_box.get() n = int(n) p = self.p_box.get() p = int(p) x01 = float(self.x01_.get()) y01 = float(self.y01_.get()) dx1 = float(self.dx1_.get()) dy1 = float(self.dy1_.get()) y02 = float(self.y02_.get()) x02 = float(self.x02_.get()) dx2 = float(self.dx2_.get()) dy2 = float(self.dy2_.get()) np_x2 = int(self.np_x2_.get()) np_y2 = int(self.np_y2_.get()) if self.transpose_chk.get() == 1: C = transpose(C) # Define the dimensions of the raw data grid np_x1 = len(C[0]) np_y1 = len(C) NP1 = np_x1 * np_y1 x1 = ones(np_x1) for i in range(0, np_x1): x1[i] = x01 + dx1 * i y1 = ones(np_y1) for i in range(0, np_y1): y1[i] = y01 + dy1 * i if self.Refl_x.get() == 1: x1_ = ones(np_x1) for i in range(0, len(x1)): x1_[i] = x1[-1 - i] x1 = x1_ data_1d = C.flatten() # Define the dimensions of interpolated data grid NP2 = np_x2 * np_y2 x2 = ones(np_x2) for i in range(0, np_x2): x2[i] = x02 + dx2 * i y2 = ones(np_y2) for i in range(0, np_y2): y2[i] = y02 + dy2 * i # Intperolation calculation k2 = 0 int_data = ones(NP2) dist = [0] * (NP1) index = [0] * (NP1) for j2 in range(0, np_y2): for i2 in range(0, np_x2): dist_2d = [] dist_1d = [] for j in range(0, np_y1): dist_2d.append([]) for i in range(0, np_x1): dist_2d[j].append( sqrt((x2[i2] - x1[i])**2 + (y2[j2] - y1[j])**2)) dist_1d.append( sqrt((x2[i2] - x1[i])**2 + (y2[j2] - y1[j])**2)) index = sorted(range(len(dist_1d)), key=lambda x: dist_1d[x]) dist = sorted(dist_1d) up = min(n, NP1) temp = 0 lamb = ones(up) if dist[0] > 0: for i in range(0, up): lamb[i] = (1/(dist[i]**p))\ /sum(ones(up)/power_(dist[0:up],p)) temp = temp + data_1d[index[i]] * lamb[i] else: temp = data_1d[index[i]] int_data[k2] = temp k2 = k2 + 1 M1 = [] N = [] k2 = 0 for j2 in range(0, np_y2): N.append([]) for i2 in range(0, np_x2): M1.append([x02 + i2 * dx2, y02 + j2 * dy2, int_data[k2]]) N[j2].append(int_data[k2]) k2 = k2 + 1 M1 = asarray(M1) N = asarray(N) # Generate a xyz equivalent array if np_x2 == np_y2: Mt = [] for j2 in range(0, np_y2): for i2 in range(0, np_x2): Mt.append([y02 + j2 * dy2, x02 + i2 * dx2, N[i2, j2]]) k2 = k2 + 1 M = append(Mt, M1, axis=1) else: M = M1 self.N = N self.M1 = M1 self.M = M self.graph1(self.N, 8) self.plot_btn.config(state='ENABLED') return (self.N, self.M1, self.M) def check_tr(self, C): self.info1_Entry.delete(10.0, END) if self.Refl_x.get() == 1: info_3 = "\nReflect x = %s" % (self.Refl_x.get()) self.info1_Entry.insert(END, info_3) if self.transpose_chk.get() == 1: info_4 = "\nTranspose = %s" % (self.transpose_chk.get()) self.info1_Entry.insert(END, info_4) self.interpolation(C) def plot(self, C, N): """Produces images of the raw and interpolated data plots""" plt.close('all') fig_ext = plt.figure(dpi=200) ax1 = fig_ext.add_subplot(121) ax1_im = plt.imshow(C, vmin=amin([amin(C), amin(N)]), vmax=amax([amax(C), amax(N)]), cmap='jet') cbar = plt.colorbar(ax1_im, orientation='vertical', fraction=0.046, pad=0.05) # aspect='auto') if self.tip.get() == 1: cbar.set_label('Work Function (meV)') else: cbar.set_label('CPD (mV)') plt.xlabel('x-axis') plt.ylabel('y-axis') ax2 = fig_ext.add_subplot(122) ax2_im = plt.imshow(N, vmin=amin([amin(C), amin(N)]), vmax=amax([amax(C), amax(N)]), cmap='jet') cbar = plt.colorbar(ax2_im, orientation='vertical', fraction=0.046, pad=0.05) #, aspect='auto') if self.tip.get() == 1: cbar.set_label('Work Function (meV)') else: cbar.set_label('CPD (mV)') plt.xlabel('x-axis') plt.ylabel('y-axis') plt.tight_layout() fig_ext = plt.gcf() plt.show() def N_out(self, N): """Exports the data as a csv file via dialogue box""" file_opt = options = {} options['filetypes'] = [('all files', '.*'), ('CSV (Comma Delimited)', '.csv')] options['initialfile'] = '.csv' options['title'] = 'Save Array as CSV' try: fo1 = filedialog.asksaveasfile(mode='wb', **file_opt) savetxt(fo1, N, delimiter=',', footer=self.info1_Entry.get(1.0, END)) fo1.close() except IOError: messagebox.showinfo(title="Output file", message="Output file issue") def workfunction(self, C): """Applies linear offset to CPD, useful for correcing for the tip's workfunction and converting CPD into workfunction""" if self.tip.get() == 1: self.C = C + float(self.tipwf.get()) self.tip_entry.config(state='disabled') else: self.C = (C - float(self.tipwf.get())) self.tip_entry.config(state="normal") self.graph1(self.C, 1) return self.C
class BattleshipsDemoClient(Frame): def __init__(self, tk, args): Frame.__init__(self, tk) # empty string for platform's default settings locale.setlocale(locale.LC_ALL, '') self.master = tk tk.title(APP_TITLE) tk.resizable(False, False) try: if WINDOWS: tk.iconbitmap("200x200/icon.ico") else: tk.iconbitmap("@200x200/icon.xbm") except Exception as e: print(e) atexit.register(self.cancel_game) # Init class data fields that we use for storing info that we need for using the API self.bot_id = None self.bot_password = None self.logged_in = False self.game_style_ids = [] self.gameChips = 0 self.gameDeals = 0 self.gameStake = 0 self.gamePrize = 0 self.player_key = None self.play_again = BooleanVar() self.do_not_play_same_user = BooleanVar() self.close_after_game = False self.game_cancelled = False self.in_game = False self.topFrame = Frame(tk, padx=12, pady=12) self.middleFrame = Frame(tk, padx=12) self.middleFrameLeft = Frame(self.middleFrame) self.middleFrameRight = Frame(self.middleFrame) self.middleFrameRighter = Frame(self.middleFrame) self.topFrame.grid(row=0, sticky=W + E) self.middleFrame.grid(row=1, sticky=W) self.middleFrameLeft.grid(row=1, column=0) self.middleFrameRight.grid(row=1, column=1) self.middleFrameRighter.grid(row=1, column=2) # =================================== # Create form elements # Top Frame Elements self.botNameLabel = Label(self.topFrame, text="Bot Name:") self.bot_id_entry = Entry(self.topFrame) self.bot_id_entry.bind('<Return>', self.log_in_if_not) self.bot_id_entry.focus() self.passwordLabel = Label(self.topFrame, text="Password:"******"Login", command=self.log_in_out_clicked) self.balanceLabel = Label(self.topFrame, text="Bot Balance:") self.balance = Label(self.topFrame, text="0") self.close_button = Button(self.topFrame, text="Close", padx=2, command=tk.destroy) # Middle Frame Elements # Middle Frame LEFT Elements self.gameStyleLabel = Label(self.middleFrameLeft, font=(None, 18), pady=0, text="Game Style Selection") self.opponentLabel = Label(self.middleFrameLeft, text="Specify Opponent (optional):") self.specify_opponent_entry = Entry(self.middleFrameLeft) self.do_not_play_same_user_check = Checkbutton( self.middleFrameLeft, text='Don\'t play another bot in same user account as me', var=self.do_not_play_same_user) self.game_styles_listbox = Listbox(self.middleFrameLeft, background='#FFFFFF', height=8) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind( '<Return>', self.find_game_double_clicked ) # Not a double click but we want it to do the same thing self.refresh_game_styles_button = Button( self.middleFrameLeft, text="Refresh Game Styles", command=self.refresh_game_styles_clicked) self.thinkingTimeLabel = Label(self.middleFrameLeft, text="Add \"Thinking Time\" (ms):") self.thinking_time_entry = Entry(self.middleFrameLeft) self.auto_play_next_game_check = Checkbutton( self.middleFrameLeft, text='Play another game when complete', var=self.play_again) self.cancel_stop_game_button = Button( self.middleFrameLeft, text=CANCEL_GAME_TEXT, command=self.cancel_stop_game_clicked) self.find_game_button = Button(self.middleFrameLeft, text="Find Game", command=self.find_game_clicked) self.resultText = Message( self.middleFrameLeft, width=300, text="This is where the informational messages will appear") self.spacerLabel = Label(self.middleFrameLeft, text=" ") # Middle Frame RIGHT Elements self.gameTitleLabel = Label(self.middleFrameRight, text="Game Title") self.gameTitleText = Text(self.middleFrameRight, height=3, background='white', spacing1=3, pady=0) self.player = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table self.opponent = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table self.gameActionLabel = Label(self.middleFrameRight, text="") # =================================== # Set initial element states self.set_gamestyle_controls_states(DISABLED) self.cancel_stop_game_button.config(state=DISABLED) self.game_styles_listbox.config(background='white') self.thinking_time_entry.insert(0, 100) self.gameTitleText.config(state=DISABLED) self.set_balance(0) self.gameTitleText.tag_configure("center", justify='center') self.gameTitleText.tag_configure("bold", font='-weight bold') # =================================== # Form Layout # Top Frame Form Layout self.topFrame.grid_rowconfigure(0, weight=1) self.botNameLabel.grid(row=0, column=0, sticky=E) self.bot_id_entry.grid(row=0, column=1, sticky=W) self.passwordLabel.grid(row=0, column=2, sticky=E) self.bot_password_entry.grid(row=0, column=3, sticky=W) self.log_in_out_button.grid(row=0, column=4, sticky=E) self.topFrame.grid_columnconfigure(5, weight=1) self.balanceLabel.grid(row=0, column=5, sticky=E) self.balance.grid(row=0, column=6, sticky=W) self.close_button.grid(row=0, column=7, sticky=E, padx=(50, 0)) # Middle Frame Form Layout self.middleFrame.grid_rowconfigure(0, weight=1) self.gameStyleLabel.grid(row=0, column=0, columnspan=1, sticky=W + E) self.spacerLabel.grid(row=0, column=2, sticky=E) self.opponentLabel.grid(row=2, column=0, sticky=W, pady=4) self.specify_opponent_entry.grid(row=2, column=0, sticky=E, pady=4) self.do_not_play_same_user_check.grid(row=3, column=0, columnspan=1, sticky='we', pady=4) self.game_styles_listbox.grid(row=4, column=0, columnspan=1, sticky='we', pady=4) self.find_game_button.grid(row=5, column=0, pady=4, sticky=W) self.refresh_game_styles_button.grid(row=5, column=0, columnspan=1, sticky='', pady=4) self.cancel_stop_game_button.grid(row=5, column=0, sticky=E) self.thinkingTimeLabel.grid(row=6, column=0, sticky=W, pady=4) self.thinking_time_entry.grid(row=6, column=0, sticky=E, pady=4) self.auto_play_next_game_check.grid(row=7, column=0, columnspan=1, sticky=W, pady=4) self.resultText.grid(row=9, column=0, columnspan=2, sticky=W, pady=4) self.middleFrame.grid_columnconfigure(9, weight=1) self.gameTitleLabel.grid(row=0, column=3) self.gameTitleText.grid(row=0, column=3, columnspan=2) self.player.grid(row=1, column=3) self.opponent.grid(row=1, column=4) self.gameActionLabel.grid(row=11, column=3, sticky='w') if args.botid is not None: self.auto_play(args) def auto_play(self, args): self.bot_id_entry.insert(0, args.botid) self.bot_password_entry.insert(0, args.password) self.log_in_out_clicked() self.thinking_time_entry.insert(0, args.timeout) if args.playanothergame: self.auto_play_next_game_check.select() if args.dontplaysameuserbot: self.do_not_play_same_user_check.select() if args.closeaftergame: self.close_after_game = True i = 0 for i in range(self.game_styles_listbox.size()): if args.gamestyle in str(self.game_styles_listbox.get(i)): break self.game_styles_listbox.select_set(i, i) self.find_game_clicked() def log_in_out_clicked(self): """Click handler for the 'Login'/'Logout' button.""" # This means we're logging out if self.logged_in: self.resultText.config(text='Logged Out') self.master.title(APP_TITLE + " (Not Logged In)") self.cancel_game() self.bot_id = 'housebot-competition' self.bot_password = None self.clear_game_title_text() self.gameActionLabel.config(text="") self.reset_game_styles_listbox() self.clear_all_boards() self.opponent.delete("all") self.log_in_out_button.config(text='Login') self.set_login_controls_states(ENABLED) self.set_gamestyle_controls_states(DISABLED) self.logged_in = False self.bot_password_entry.delete(0, 'end') self.set_balance(0) # This means we're logging in else: self.bot_id = self.bot_id_entry.get() self.bot_password = '******' res = self.get_list_of_game_styles() if res['Result'] == 'SUCCESS': self.resultText.config(text='Logged In') game_styles = res['GameStyles'] self.master.title(self.bot_id + " - " + APP_TITLE) self.set_login_controls_states(DISABLED) self.set_gamestyle_controls_states(ENABLED) self.set_game_styles_listbox(game_styles) self.set_balance(res['Balance']) self.log_in_out_button.config(text='Logout') self.logged_in = True else: messagebox.showerror( 'Error', 'Invalid login attempt. Please check the username and password entered.' ) def log_in_if_not(self, _): if not self.logged_in: self.log_in_out_clicked() def clear_all_boards(self): self.player.delete("all") self.opponent.delete("all") self.player.myBoard = None self.opponent.oppBoard = None def set_in_game(self, value): self.in_game = value def set_game_title_text(self, text, tag): self.gameTitleText.config(state=ENABLED) self.gameTitleText.insert("end", text, ("center", tag)) self.gameTitleText.config(state=DISABLED) def clear_game_title_text(self): self.gameTitleText.config(state=ENABLED) self.gameTitleText.delete("1.0", "end") self.gameTitleText.config(state=DISABLED) def set_login_controls_states(self, state): self.bot_id_entry.config(state=state) self.bot_password_entry.config(state=state) def set_gamestyle_controls_states(self, state): self.specify_opponent_entry.config(state=state) self.do_not_play_same_user_check.config(state=state) self.game_styles_listbox.config(state=state) self.find_game_button.config(state=state) self.refresh_game_styles_button.config(state=state) self.auto_play_next_game_check.config(state=state) self.thinking_time_entry.config(state=state) self.opponentLabel.config(state=state) self.thinkingTimeLabel.config(state=state) self.balanceLabel.config(state=state) self.balance.config(state=state) self.gameStyleLabel.config(state=state) self.game_styles_listbox.config(state=state) self.player.config(state=state) self.opponent.config(state=state) def set_balance(self, balance): """Set the balance field""" self.balance['text'] = int_with_commas(balance) self.balance['text'] += ' sat' def get_list_of_game_styles(self): """Get list of game styles from the server.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'GameTypeId': BATTLESHIPS_GAME_TYPE_ID } url = BASE_URL + GET_LIST_OF_GAME_STYLES_EXTENSION return BattleshipsDemoClient.make_api_call(url, req) def set_game_styles_listbox(self, game_styles): """Set the content of the game styles listbox with a list of GameStyle dictionaries. Keyword Arguments: game_styles -- The list of GameStyle dictionaries, this should be obtained through get_list_of_game_styles(). """ self.reset_game_styles_listbox() for index, game_style in enumerate(game_styles): self.game_styles_listbox.insert( index, GAME_STYLE_LISTBOX_TEXT.format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Ships'], game_style['GameTypeSpecificInfo']['Board Size'], game_style['GameTypeSpecificInfo']['Timeout ms'], game_style['GameTypeSpecificInfo']['DealsTotal'], game_style['GameTypeSpecificInfo']['PercentageLand'], game_style['GameTypeSpecificInfo']['RandomLand'])) self.game_style_ids.append(game_style['GameStyleId']) # self.game_styles_listbox.select_set(GAME_STYLE_LISTBOX_DEFAULT_SELECTION) def reset_game_styles_listbox(self): """Clear the content of the game styles listbox.""" if self.game_styles_listbox.size() != 0: self.game_styles_listbox.delete(0, 'end') self.game_style_ids = [] def refresh_game_styles_clicked(self): """Click handler for the 'Refresh Game Styles' button.""" res = self.get_list_of_game_styles() game_styles = res['GameStyles'] self.set_game_styles_listbox(game_styles) def find_game_clicked(self): """Click handler for the 'Find Game' button""" self.find_game_button.config(state=DISABLED) self.cancel_stop_game_button.config(state=ENABLED) self.clear_all_boards() # Here we dispatch the work to a separate thread, to keep the GUI responsive. if not MAC: threading.Thread(target=self.game_loop, daemon=True).start() else: self.game_loop() # Doesn't work on MACs def find_game_double_clicked(self, _): self.find_game_clicked() def game_loop(self): """Loop through finding and playing games.""" while True: self.clear_all_boards() self.find_game() if self.game_cancelled: break self.play_game() if self.close_after_game: self.close_button.invoke() if self.game_cancelled: break if not self.play_again.get(): break self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_cancelled = False def find_game(self): """Find a game.""" offer_game_res = self.offer_game() if offer_game_res['Result'] == 'INVALID_LOGIN_OR_PASSWORD': self.cancel_stop_game_clicked() if 'ErrorMessage' in offer_game_res and offer_game_res[ 'ErrorMessage'] == 'Check of OpponentId failed': self.resultText.config(text='Invalid Opponent ID') else: self.resultText.config(text='Invalid login or password') elif offer_game_res['Result'] == 'INSUFFICIENT_BALANCE': self.cancel_stop_game_clicked() self.resultText.config(text='Insufficient balance') elif offer_game_res['Result'] == 'BOT_IS_INACTIVE': self.cancel_stop_game_clicked() self.resultText.config(text='Bot is inactive') else: self.player_key = offer_game_res['PlayerKey'] if offer_game_res['Result'] == 'WAITING_FOR_GAME': self.wait_for_game() def offer_game(self): """Offer a game.""" opponent_id = self.specify_opponent_entry.get() if len(opponent_id) == 0: opponent_id = None try: game_style_id = self.game_style_ids[int( self.game_styles_listbox.curselection()[0])] except IndexError: self.game_styles_listbox.select_set( GAME_STYLE_LISTBOX_DEFAULT_SELECTION) game_style_id = self.game_style_ids[0] req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'GameStyleId': game_style_id, 'DontPlayAgainstSameUser': self.do_not_play_same_user.get(), 'DontPlayAgainstSameBot': False, 'OpponentId': opponent_id } url = BASE_URL + OFFER_GAME_EXTENSION return BattleshipsDemoClient.make_api_call(url, req) def wait_for_game(self): """Wait for game to start.""" self.resultText.config(text='Waiting for game') while True: if self.game_cancelled: self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) break poll_results = self.poll_for_game_state() if poll_results['Result'] == 'SUCCESS': break if poll_results['Result'] == 'INVALID_PLAYER_KEY' or poll_results[ 'Result'] == 'GAME_HAS_ENDED' or poll_results[ 'Result'] == 'GAME_WAS_STOPPED': self.game_cancelled = True time.sleep(2) def play_game(self): """Play a game.""" self.resultText.config(text='Playing game') self.in_game = True poll_results = self.poll_for_game_state() if poll_results["Result"] != "SUCCESS": return game_state = poll_results['GameState'] title = format('Game ID: ' + str(game_state['GameId'])) game_style_details = self.game_styles_listbox.get('active').split( " | ") title += format(' / Style: ' + str(self.game_style_ids[int( self.game_styles_listbox.curselection()[0])])) title += format(' / Land: ' + game_style_details[6].split(" ")[2] + '%') title += format(' / Deals: ' + game_style_details[5].split(" ")[1]) title += format(' / ' + game_style_details[7]) title += "\n" versus = format(self.bot_id + ' vs ' + game_state['OpponentId']) self.clear_game_title_text() self.set_game_title_text(title, "") self.set_game_title_text(versus, "bold") self.middleFrame.update() while True: if self.game_cancelled: break if game_state['IsMover']: self.resultText.config(text='Playing Game - Your Turn') move = battleships_move.calculateMove(game_state) move_results = self.make_move(move) if move_results['Result'] == 'INVALID_MOVE': self.resultText.config(text="Invalid Move") elif move_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + move_results['Result']) print("Game ended") break else: game_state = move_results['GameState'] else: self.resultText.config(text="Playing Game - Opponent's Turn") # ---- Code here will be called on your opponent's turn ---- # ---------------------------------------------------------- poll_results = self.poll_for_game_state() if poll_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + poll_results['Result']) break game_state = poll_results['GameState'] if game_state['GameStatus'] != 'RUNNING': break self.middleFrameRight.update() try: if int(self.thinking_time_entry.get()) > 0: time.sleep((int(self.thinking_time_entry.get()) / 1000)) else: time.sleep(0.1) except ValueError: time.sleep(0.1) self.set_in_game(False) def make_move(self, move): """Make a move.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key, 'Move': move } url = BASE_URL + MAKE_MOVE_EXTENSION result = BattleshipsDemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: print(result) try: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) except Exception as e: print("Gamestate error: " + str(e)) return result def poll_for_game_state(self): """Poll the server for the latest GameState.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'PlayerKey': self.player_key } url = BASE_URL + POLL_FOR_GAME_STATE_EXTENSION result = BattleshipsDemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) return result def cancel_stop_game_clicked(self): self.game_cancelled = True self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) def cancel_game(self): if self.player_key is None: return req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key } url = BASE_URL + CANCEL_GAME_OFFER_EXTENSION BattleshipsDemoClient.make_api_call(url, req) try: self.resultText.config(text='Cancelled game') except Exception as e: print(str(e) + " -- resultText Message object no longer exists") @staticmethod def make_api_call(url, req): """Make an API call.""" while True: try: res = requests.post(url, json=req, headers=API_CALL_HEADERS, timeout=60.0) try: jres = res.json() if 'Result' in jres: return jres time.sleep(0.1) except ValueError: time.sleep(0.1) except requests.ConnectionError: time.sleep(0.1) except requests.Timeout: time.sleep(0.1) except requests.HTTPError: time.sleep(0.1) except BaseException as e: # Bad code but needed for testing purposes print(e) time.sleep(0.1)
class SettingsFrame(Frame): ''' Frame inheritance class for application settings and controls. ''' def __init__(self, app, *args, **kwargs): ''' Constructor. ''' self.__app = app # Reference to main application class self.__master = self.__app.get_master() # Reference to root class (Tk) Frame.__init__(self, self.__master, *args, **kwargs) self._show_advanced = False self._settings = {} self._ports = () self._port = StringVar() self._port_desc = StringVar() self._baudrate = IntVar() self._databits = IntVar() self._stopbits = DoubleVar() self._parity = StringVar() self._rtscts = IntVar() self._xonxoff = IntVar() self._protocol = IntVar() self._raw = IntVar() self._autoscroll = IntVar() self._maxlines = IntVar() self._webmap = IntVar() self._mapzoom = IntVar() self._units = StringVar() self._format = StringVar() self._datalog = IntVar() self._record_track = IntVar() self._noports = True self._validsettings = True self._logpath = None self._trackpath = None self._img_conn = ImageTk.PhotoImage(Image.open(ICON_CONN)) self._img_disconn = ImageTk.PhotoImage(Image.open(ICON_DISCONN)) self._img_ubxconfig = ImageTk.PhotoImage(Image.open(ICON_UBXCONFIG)) self._img_dataread = ImageTk.PhotoImage(Image.open(ICON_LOGREAD)) self._body() self._do_layout() self._get_ports() self._reset() def _body(self): ''' Set up frame and widgets. ''' for i in range(4): self.grid_columnconfigure(i, weight=1) self.grid_rowconfigure(0, weight=1) self.option_add("*Font", self.__app.font_sm) # Serial port settings self._frm_basic = Frame(self) self._lbl_port = Label(self._frm_basic, text="Port") self._lbx_port = Listbox(self._frm_basic, border=2, relief="sunken", bg=ENTCOL, width=28, height=5, justify=LEFT, exportselection=False) self._scr_portv = Scrollbar(self._frm_basic, orient=VERTICAL) self._scr_porth = Scrollbar(self._frm_basic, orient=HORIZONTAL) self._lbx_port.config(yscrollcommand=self._scr_portv.set) self._lbx_port.config(xscrollcommand=self._scr_porth.set) self._scr_portv.config(command=self._lbx_port.yview) self._scr_porth.config(command=self._lbx_port.xview) self._lbx_port.bind("<<ListboxSelect>>", self._on_select_port) self._lbl_baudrate = Label(self._frm_basic, text="Baud rate") self._spn_baudrate = Spinbox(self._frm_basic, values=(BAUDRATES), width=8, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._baudrate) self._btn_toggle = Button(self._frm_basic, text=ADVOFF, width=3, command=self._toggle_advanced) self._frm_advanced = Frame(self) self._lbl_databits = Label(self._frm_advanced, text="Data Bits") self._spn_databits = Spinbox(self._frm_advanced, values=(8, 7, 6, 5), width=3, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._databits) self._lbl_stopbits = Label(self._frm_advanced, text="Stop Bits") self._spn_stopbits = Spinbox(self._frm_advanced, values=(2, 1.5, 1), width=3, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._stopbits) self._lbl_parity = Label(self._frm_advanced, text="Parity") self._spn_parity = Spinbox(self._frm_advanced, values=("None", "Even", "Odd", "Mark", "Space"), width=6, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._parity) self._chk_rts = Checkbutton(self._frm_advanced, text="RTS/CTS", variable=self._rtscts) self._chk_xon = Checkbutton(self._frm_advanced, text="Xon/Xoff", variable=self._xonxoff) self._frm_buttons = Frame(self) self._btn_connect = Button(self._frm_buttons, width=45, height=35, image=self._img_conn, command=lambda: self.__app.serial_handler.connect()) self._btn_disconnect = Button(self._frm_buttons, width=45, height=35, image=self._img_disconn, command=lambda: self.__app.serial_handler.disconnect(), state=DISABLED) self._btn_connect_file = Button(self._frm_buttons, width=45, height=35, image=self._img_dataread, command=lambda: self._on_data_stream()) self._lbl_status_preset = Label(self._frm_buttons, font=self.__app.font_md2, text='') # Other configuration options self._frm_options = Frame(self) self._lbl_protocol = Label(self._frm_options, text=LBLPROTDISP) self._rad_nmea = Radiobutton(self._frm_options, text="NMEA", variable=self._protocol, value=NMEA_PROTOCOL) self._rad_ubx = Radiobutton(self._frm_options, text="UBX", variable=self._protocol, value=UBX_PROTOCOL) self._rad_all = Radiobutton(self._frm_options, text="ALL", variable=self._protocol, value=MIXED_PROTOCOL) self._lbl_consoledisplay = Label(self._frm_options, text=LBLDATADISP) self._rad_parsed = Radiobutton(self._frm_options, text="Parsed", variable=self._raw, value=0) self._rad_raw = Radiobutton(self._frm_options, text="Raw", variable=self._raw, value=1) self._lbl_format = Label(self._frm_options, text="Degrees Format") self._spn_format = Spinbox(self._frm_options, values=(DDD, DMS, DMM), width=6, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._format) self._lbl_units = Label(self._frm_options, text="Units") self._spn_units = Spinbox(self._frm_options, values=(UMM, UIK, UI, UMK), width=13, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._units) self._chk_scroll = Checkbutton(self._frm_options, text="Autoscroll", variable=self._autoscroll) self._spn_maxlines = Spinbox(self._frm_options, values=("100", "200", "500", "1000", "2000"), width=6, readonlybackground=ENTCOL, wrap=True, textvariable=self._maxlines, state=READONLY) self._chk_webmap = Checkbutton(self._frm_options, text="Web Map Zoom", variable=self._webmap) self._scl_mapzoom = Scale(self._frm_options, from_=1, to=20, orient=HORIZONTAL, relief="sunken", bg=ENTCOL, variable=self._mapzoom) self._chk_datalog = Checkbutton(self._frm_options, text=LBLDATALOG, variable=self._datalog, command=lambda: self._on_data_log()) self._chk_recordtrack = Checkbutton(self._frm_options, text=LBLTRACKRECORD, variable=self._record_track, command=lambda: self._on_record_track()) self._lbl_ubxconfig = Label(self._frm_options, text=LBLUBXCONFIG) self._btn_ubxconfig = Button(self._frm_options, width=45, height=35, text='UBX', image=self._img_ubxconfig, command=lambda: self._on_ubx_config(), state=DISABLED) def _do_layout(self): ''' Position widgets in frame. ''' self._frm_basic.grid(column=0, row=0, columnspan=4, sticky=(W, E)) self._lbl_port.grid(column=0, row=0, sticky=(W)) self._lbx_port.grid(column=1, row=0, sticky=(W, E), padx=3, pady=3) self._scr_portv.grid(column=2, row=0, sticky=(N, S)) self._scr_porth.grid(column=1, row=1, sticky=(E, W)) self._lbl_baudrate.grid(column=0, row=2, sticky=(W)) self._spn_baudrate.grid(column=1, row=2, sticky=(W), padx=3, pady=3) self._btn_toggle.grid(column=2, row=2, sticky=(E)) self._frm_advanced.grid_forget() self._lbl_databits.grid(column=0, row=0, sticky=(W)) self._spn_databits.grid(column=1, row=0, sticky=(W), padx=3, pady=3) self._lbl_stopbits.grid(column=2, row=0, sticky=(W)) self._spn_stopbits.grid(column=3, row=0, sticky=(W), padx=3, pady=3) self._lbl_parity.grid(column=0, row=1, sticky=(W)) self._spn_parity.grid(column=1, row=1, sticky=(W), padx=3, pady=3) self._chk_rts.grid(column=2, row=1, sticky=(W)) self._chk_xon.grid(column=3, row=1, sticky=(W), padx=3, pady=3) ttk.Separator(self).grid(column=0, row=2, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_buttons.grid(column=0, row=3, columnspan=4, sticky=(W, E)) self._btn_connect.grid(column=0, row=0, padx=3, pady=3) self._btn_connect_file.grid(column=1, row=0, padx=3, pady=3) self._btn_disconnect.grid(column=3, row=0, padx=3, pady=3) ttk.Separator(self).grid(column=0, row=7, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_options.grid(column=0, row=8, columnspan=4, sticky=(W, E)) self._lbl_protocol.grid(column=0, row=0, padx=3, pady=3, sticky=(W)) self._rad_nmea.grid(column=1, row=0, padx=0, pady=0, sticky=(W)) self._rad_ubx.grid(column=2, row=0, padx=0, pady=0, sticky=(W)) self._rad_all.grid(column=3, row=0, padx=0, pady=0, sticky=(W)) self._lbl_consoledisplay.grid(column=0, row=1, padx=2, pady=3, sticky=(W)) self._rad_parsed.grid(column=1, row=1, padx=1, pady=3, sticky=(W)) self._rad_raw.grid(column=2, row=1, padx=2, pady=3, sticky=(W)) self._lbl_format.grid(column=0, row=2, padx=3, pady=3, sticky=(W)) self._spn_format.grid(column=1, row=2, padx=2, pady=3, sticky=(W)) self._lbl_units.grid(column=0, row=3, padx=3, pady=3, sticky=(W)) self._spn_units.grid(column=1, row=3, columnspan=3, padx=2, pady=3, sticky=(W)) self._chk_scroll.grid(column=0, row=4, padx=3, pady=3, sticky=(W)) self._spn_maxlines.grid(column=1, row=4, columnspan=3, padx=3, pady=3, sticky=(W)) self._chk_webmap.grid(column=0, row=5, sticky=(W)) self._scl_mapzoom.grid(column=1, row=5, columnspan=3, sticky=(W)) self._chk_datalog.grid(column=0, row=6, padx=3, pady=3, sticky=(W)) self._chk_recordtrack.grid(column=0, row=7, padx=3, pady=3, sticky=(W)) ttk.Separator(self._frm_options).grid(column=0, row=8, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._lbl_ubxconfig.grid(column=0, row=9, padx=3, pady=3, sticky=(W)) self._btn_ubxconfig.grid(column=1, row=9, padx=3, pady=3, sticky=(W)) def _on_select_port(self, *args, **kwargs): ''' Get selected port from listbox and set global variable. ''' idx = self._lbx_port.curselection() if idx == "": idx = 0 port_orig = self._lbx_port.get(idx) port = port_orig[0:port_orig.find(":")] desc = port_orig[port_orig.find(":") + 1:] if desc == '': desc = "device" self._port.set(port) self._port_desc.set(desc) def _on_ubx_config(self, *args, **kwargs): ''' Open UBX configuration dialog panel. ''' self.__app.ubxconfig() def _on_data_log(self): ''' Start or stop data logger ''' if self._datalog.get() == 1: self._logpath = self.__app.file_handler.set_logfile_path() if self._logpath is not None: self.__app.set_status("Data logging enabled: " + self._logpath, "green") else: self._datalog.set(False) else: self._logpath = None self._datalog.set(False) # self.__app.file_handler.close_logfile() self.__app.set_status("Data logging disabled", "blue") def _on_record_track(self): ''' Start or stop track recorder ''' if self._record_track.get() == 1: self._trackpath = self.__app.file_handler.set_trackfile_path() if self._trackpath is not None: self.__app.set_status("Track recording enabled: " + self._trackpath, "green") else: self._record_track.set(False) else: self._trackpath = None self._record_track.set(False) # self.__app.file_handler.close_trackfile() self.__app.set_status("Track recording disabled", "blue") def _on_data_stream(self): ''' Start data file streamer ''' self._logpath = self.__app.file_handler.open_logfile_input() if self._logpath is not None: self.__app.set_status("") self.__app.serial_handler.connect_file() def _toggle_advanced(self): ''' Toggle advanced serial port settings panel on or off ''' self._show_advanced = not self._show_advanced if self._show_advanced: self._frm_advanced.grid(column=0, row=1, columnspan=3, sticky=(W, E)) self._btn_toggle.config(text=ADVON) else: self._frm_advanced.grid_forget() self._btn_toggle.config(text=ADVOFF) def _get_ports(self): ''' Populate list of available serial ports using pyserial comports tool. If no ports found, disable all connection-dependent widgets. Attempt to preselect the first port that has a recognisable GPS designation in its description (usually only works on Posix platforms - Windows doesn't parse UART device desc or HWID) ''' self._ports = sorted(comports()) init_idx = 0 port = '' desc = '' if len(self._ports) > 0: for idx, (port, desc, _) in enumerate(self._ports, 1): self._lbx_port.insert(idx, port + ": " + desc) for kgp in KNOWNGPS: if kgp in desc: init_idx = idx break self._noports = False else: self._noports = True self.set_controls(NOPORTS) self._lbx_port.activate(init_idx) self._port.set(port) self._port_desc.set(desc) def _reset(self): ''' Reset settings to defaults. ''' self._baudrate.set(BAUDRATES[4]) # 9600 self._databits.set(8) self._stopbits.set(1) self._parity.set("None") self._rtscts.set(False) self._xonxoff.set(False) self._protocol.set(MIXED_PROTOCOL) self._format.set(DDD) self._units.set(UMM) self._autoscroll.set(1) self._maxlines.set(300) self._raw.set(False) self._webmap.set(False) self._mapzoom.set(10) self._datalog.set(False) self._record_track.set(False) def set_controls(self, status): ''' ...for the heart of the sun. Public method to enable and disable serial port controls depending on connection status. ''' self._lbl_port.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._lbx_port.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._lbl_baudrate.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_baudrate.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._lbl_databits.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_databits.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._lbl_stopbits.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_stopbits.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._lbl_parity.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_parity.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._chk_rts.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._chk_xon.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._btn_connect.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE, NOPORTS) \ else NORMAL)) self._btn_disconnect.config(state=(DISABLED if status in \ (DISCONNECTED, NOPORTS) else NORMAL)) self._chk_datalog.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE, NOPORTS) \ else NORMAL)) self._chk_recordtrack.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE) \ else NORMAL)) self._btn_connect_file.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE) \ else NORMAL)) self._btn_ubxconfig.config(state=(DISABLED if status in \ (DISCONNECTED, CONNECTED_FILE, NOPORTS) \ else NORMAL)) self.__app.menu.options_menu.entryconfig(0, state=(DISABLED if status in \ (CONNECTED_FILE, DISCONNECTED, NOPORTS) \ else NORMAL)) def get_settings(self): ''' Public method returns all settings as a dict. ''' self._settings['port'] = self._port.get() self._settings['noports'] = self._noports self._settings['port_desc'] = self._port_desc.get() self._settings['baudrate'] = self._baudrate.get() self._settings['databits'] = self._databits.get() self._settings['stopbits'] = self._stopbits.get() self._settings['parity'] = self._parity.get() self._settings['rtscts'] = self._rtscts.get() self._settings['xonxoff'] = self._xonxoff.get() self._settings['protocol'] = self._protocol.get() self._settings['raw'] = self._raw.get() self._settings['autoscroll'] = self._autoscroll.get() self._settings['maxlines'] = self._maxlines.get() self._settings['webmap'] = self._webmap.get() self._settings['mapzoom'] = self._mapzoom.get() self._settings['units'] = self._units.get() self._settings['format'] = self._format.get() self._settings['logpath'] = self._logpath self._settings['datalogging'] = self._datalog.get() self._settings['recordtrack'] = self._record_track.get() return self._settings def get_size(self): ''' Get current frame size. ''' self.update_idletasks() # Make sure we know about any resizing return (self.winfo_width(), self.winfo_height())
class SettingsFrame(Frame): """ Frame inheritance class for application settings and controls. """ def __init__(self, app, *args, **kwargs): """ Constructor. :param object app: reference to main tkinter application """ self.__app = app # Reference to main application class self.__master = self.__app.get_master() # Reference to root class (Tk) Frame.__init__(self, self.__master, *args, **kwargs) self._settings = {} self._protocol = IntVar() self._raw = IntVar() self._autoscroll = IntVar() self._maxlines = IntVar() self._webmap = IntVar() self._mapzoom = IntVar() self._units = StringVar() self._format = StringVar() self._datalog = IntVar() self._record_track = IntVar() self._show_zerosig = IntVar() self._show_legend = IntVar() self._validsettings = True self._logpath = None self._trackpath = None self._img_conn = ImageTk.PhotoImage(Image.open(ICON_CONN)) self._img_disconn = ImageTk.PhotoImage(Image.open(ICON_DISCONN)) self._img_ubxconfig = ImageTk.PhotoImage(Image.open(ICON_UBXCONFIG)) self._img_dataread = ImageTk.PhotoImage(Image.open(ICON_LOGREAD)) self._body() self._do_layout() self._reset() def _body(self): """ Set up frame and widgets. """ for i in range(4): self.grid_columnconfigure(i, weight=1) self.grid_rowconfigure(0, weight=1) self.option_add("*Font", self.__app.font_sm) # serial port configuration panel self._frm_serial = SerialConfigFrame(self, preselect=KNOWNGPS) # connection buttons self._frm_buttons = Frame(self) self._btn_connect = Button( self._frm_buttons, width=45, height=35, image=self._img_conn, command=lambda: self.__app.serial_handler.connect(), ) self._btn_disconnect = Button( self._frm_buttons, width=45, height=35, image=self._img_disconn, command=lambda: self.__app.serial_handler.disconnect(), state=DISABLED, ) self._btn_connect_file = Button( self._frm_buttons, width=45, height=35, image=self._img_dataread, command=lambda: self._on_data_stream(), ) self._lbl_status_preset = Label(self._frm_buttons, font=self.__app.font_md2, text="") # Other configuration options self._frm_options = Frame(self) self._lbl_protocol = Label(self._frm_options, text=LBLPROTDISP) self._rad_nmea = Radiobutton(self._frm_options, text="NMEA", variable=self._protocol, value=NMEA_PROTOCOL) self._rad_ubx = Radiobutton(self._frm_options, text="UBX", variable=self._protocol, value=UBX_PROTOCOL) self._rad_all = Radiobutton(self._frm_options, text="ALL", variable=self._protocol, value=MIXED_PROTOCOL) self._lbl_consoledisplay = Label(self._frm_options, text=LBLDATADISP) self._rad_parsed = Radiobutton(self._frm_options, text="Parsed", variable=self._raw, value=0) self._rad_raw = Radiobutton(self._frm_options, text="Raw", variable=self._raw, value=1) self._lbl_format = Label(self._frm_options, text="Degrees Format") self._spn_format = Spinbox( self._frm_options, values=(DDD, DMS, DMM), width=6, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._format, ) self._lbl_units = Label(self._frm_options, text="Units") self._spn_units = Spinbox( self._frm_options, values=(UMM, UIK, UI, UMK), width=13, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._units, ) self._chk_scroll = Checkbutton(self._frm_options, text="Autoscroll", variable=self._autoscroll) self._spn_maxlines = Spinbox( self._frm_options, values=("100", "200", "500", "1000", "2000"), width=6, readonlybackground=ENTCOL, wrap=True, textvariable=self._maxlines, state=READONLY, ) self._chk_webmap = Checkbutton( self._frm_options, text="Web Map Zoom", variable=self._webmap, command=lambda: self._on_webmap(), ) self._scl_mapzoom = Scale( self._frm_options, from_=1, to=20, orient=HORIZONTAL, relief="sunken", bg=ENTCOL, variable=self._mapzoom, ) self._chk_zerosig = Checkbutton(self._frm_options, text=LBLSHOWNULL, variable=self._show_zerosig) self._chk_legend = Checkbutton(self._frm_options, text=LBLLEGEND, variable=self._show_legend) self._chk_datalog = Checkbutton( self._frm_options, text=LBLDATALOG, variable=self._datalog, command=lambda: self._on_data_log(), ) self._chk_recordtrack = Checkbutton( self._frm_options, text=LBLTRACKRECORD, variable=self._record_track, command=lambda: self._on_record_track(), ) self._lbl_ubxconfig = Label(self._frm_options, text=LBLUBXCONFIG) self._btn_ubxconfig = Button( self._frm_options, width=45, height=35, text="UBX", image=self._img_ubxconfig, command=lambda: self._on_ubx_config(), state=DISABLED, ) def _do_layout(self): """ Position widgets in frame. """ self._frm_serial.grid(column=0, row=1, columnspan=4, padx=3, pady=3, sticky=(W, E)) ttk.Separator(self).grid(column=0, row=2, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_buttons.grid(column=0, row=3, columnspan=4, sticky=(W, E)) self._btn_connect.grid(column=0, row=0, padx=3, pady=3) self._btn_connect_file.grid(column=1, row=0, padx=3, pady=3) self._btn_disconnect.grid(column=3, row=0, padx=3, pady=3) ttk.Separator(self).grid(column=0, row=7, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_options.grid(column=0, row=8, columnspan=4, sticky=(W, E)) self._lbl_protocol.grid(column=0, row=0, padx=3, pady=3, sticky=(W)) self._rad_nmea.grid(column=1, row=0, padx=0, pady=0, sticky=(W)) self._rad_ubx.grid(column=2, row=0, padx=0, pady=0, sticky=(W)) self._rad_all.grid(column=3, row=0, padx=0, pady=0, sticky=(W)) self._lbl_consoledisplay.grid(column=0, row=1, padx=2, pady=3, sticky=(W)) self._rad_parsed.grid(column=1, row=1, padx=1, pady=3, sticky=(W)) self._rad_raw.grid(column=2, row=1, padx=2, pady=3, sticky=(W)) self._lbl_format.grid(column=0, row=2, padx=3, pady=3, sticky=(W)) self._spn_format.grid(column=1, row=2, padx=2, pady=3, sticky=(W)) self._lbl_units.grid(column=0, row=3, padx=3, pady=3, sticky=(W)) self._spn_units.grid(column=1, row=3, columnspan=3, padx=2, pady=3, sticky=(W)) self._chk_scroll.grid(column=0, row=4, padx=3, pady=3, sticky=(W)) self._spn_maxlines.grid(column=1, row=4, columnspan=3, padx=3, pady=3, sticky=(W)) self._chk_webmap.grid(column=0, row=5, padx=3, pady=3, sticky=(W)) self._scl_mapzoom.grid(column=1, row=5, columnspan=3, sticky=(W)) self._chk_legend.grid(column=0, row=6, padx=3, pady=3, sticky=(W)) self._chk_zerosig.grid(column=1, row=6, columnspan=2, padx=3, pady=3, sticky=(W)) self._chk_datalog.grid(column=0, row=7, padx=3, pady=3, sticky=(W)) self._chk_recordtrack.grid(column=1, row=7, columnspan=2, padx=3, pady=3, sticky=(W)) ttk.Separator(self._frm_options).grid(column=0, row=8, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._lbl_ubxconfig.grid(column=0, row=9, padx=3, pady=3, sticky=(W)) self._btn_ubxconfig.grid(column=1, row=9, padx=3, pady=3, sticky=(W)) def _on_ubx_config(self, *args, **kwargs): # pylint: disable=unused-argument """ Open UBX configuration dialog panel. """ self.__app.ubxconfig() def _on_webmap(self): """ Reset webmap refresh timer """ self.__app.frm_mapview.reset_map_refresh() def _on_data_log(self): """ Start or stop data logger """ if self._datalog.get() == 1: self._logpath = self.__app.file_handler.set_logfile_path() if self._logpath is not None: self.__app.set_status("Data logging enabled: " + self._logpath, "green") else: self._datalog.set(False) else: self._logpath = None self._datalog.set(False) # self.__app.file_handler.close_logfile() self.__app.set_status("Data logging disabled", "blue") def _on_record_track(self): """ Start or stop track recorder """ if self._record_track.get() == 1: self._trackpath = self.__app.file_handler.set_trackfile_path() if self._trackpath is not None: self.__app.set_status( "Track recording enabled: " + self._trackpath, "green") else: self._record_track.set(False) else: self._trackpath = None self._record_track.set(False) # self.__app.file_handler.close_trackfile() self.__app.set_status("Track recording disabled", "blue") def _on_data_stream(self): """ Start data file streamer """ self._logpath = self.__app.file_handler.open_logfile_input() if self._logpath is not None: self.__app.set_status("") self.__app.serial_handler.connect_file() def _reset(self): """ Reset settings to defaults. """ self._protocol.set(MIXED_PROTOCOL) self._format.set(DDD) self._units.set(UMM) self._autoscroll.set(1) self._maxlines.set(300) self._raw.set(False) self._webmap.set(False) self._mapzoom.set(10) self._show_legend.set(True) self._show_zerosig.set(False) self._datalog.set(False) self._record_track.set(False) def set_controls(self, status: int): """ ...for the heart of the sun. Public method to enable and disable serial port controls depending on connection status. :param int status: connection status as integer (0,1,2) """ self._frm_serial.set_controls(status) self._btn_connect.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE, NOPORTS) else NORMAL)) self._btn_disconnect.config( state=(DISABLED if status in (DISCONNECTED, NOPORTS) else NORMAL)) self._chk_datalog.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE, NOPORTS) else NORMAL)) self._chk_recordtrack.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE) else NORMAL)) self._btn_connect_file.config( state=(DISABLED if status in (CONNECTED, CONNECTED_FILE) else NORMAL)) self._btn_ubxconfig.config( state=(DISABLED if status in (DISCONNECTED, CONNECTED_FILE, NOPORTS) else NORMAL)) self.__app.menu.options_menu.entryconfig( 0, state=(DISABLED if status in (CONNECTED_FILE, DISCONNECTED, NOPORTS) else NORMAL), ) def get_settings(self) -> dict: """ Public method returns all settings as a dict. :return current settings :rtype dict """ self._settings["noports"] = self._frm_serial.noports self._settings["port"] = self._frm_serial.port self._settings["port_desc"] = self._frm_serial.port_desc self._settings["baudrate"] = self._frm_serial.baudrate self._settings["databits"] = self._frm_serial.databits self._settings["stopbits"] = self._frm_serial.stopbits self._settings["parity"] = self._frm_serial.parity self._settings["rtscts"] = self._frm_serial.rtscts self._settings["xonxoff"] = self._frm_serial.xonxoff self._settings["protocol"] = self._protocol.get() self._settings["raw"] = self._raw.get() self._settings["autoscroll"] = self._autoscroll.get() self._settings["maxlines"] = self._maxlines.get() self._settings["webmap"] = self._webmap.get() self._settings["mapzoom"] = self._mapzoom.get() self._settings["units"] = self._units.get() self._settings["format"] = self._format.get() self._settings["logpath"] = self._logpath self._settings["datalogging"] = self._datalog.get() self._settings["recordtrack"] = self._record_track.get() self._settings["zerosignal"] = self._show_zerosig.get() self._settings["graphlegend"] = self._show_legend.get() return self._settings def get_size(self) -> (int, int): """ Get current frame size. :return (width, height) :rtype tuple """ self.update_idletasks() # Make sure we know about any resizing return (self.winfo_width(), self.winfo_height())
class Tab(ABC): def __init__(self, view, tab_control): self.view = view self.bandas_estandar_repository = RepositoryProvider.provide_bandas_estandar_repository( ) self.tab_frame = tab_control.agregar_tab(self, self.titulo_tab) self.construir_tab() @abstractmethod def obtener_bandas(self): pass def construir_tab(self): self.construir_frame_titulo() self.construir_frame_grafica() self.construir_frame_medicion() def construir_frame_titulo(self): self.frame_titulo_grafica = Frame(self.tab_frame) self.frame_titulo_grafica.config(width=400, borderwidth=2, relief="groove") self.frame_titulo_grafica.grid(row=0, column=0, sticky="nsew", padx=10, pady=(15, 0)) self.label_titulo_grafica = Label(self.frame_titulo_grafica) self.label_titulo_grafica.config( text="Nivel de respuesta impulsional - Curva de decaimiento", bg="#0c005a") self.label_titulo_grafica.pack(fill="both", expand="True") def construir_frame_grafica(self): self.frame_grafica = Frame(self.tab_frame) self.frame_grafica.grid(row=1, column=0, padx=10, pady=10) self.frame_label_grafica = Frame(self.frame_grafica) self.frame_label_grafica.config(width=600, height=400) self.frame_label_grafica.pack_propagate(False) self.frame_label_grafica.grid(row=0, column=0) self.label_grafica = Label(self.frame_label_grafica) self.label_grafica.config(borderwidth=2, relief="groove", bg="#5893d4") self.label_grafica.pack(expand="True", fill="both") self.frame_toolbar = Frame(self.frame_grafica) self.frame_toolbar.config(width=400, height=40, borderwidth=2) self.frame_toolbar.pack_propagate(False) self.frame_toolbar.grid(row=1, column=0, sticky="nsew") self.construir_plot() def construir_plot(self): self.figura = Figure(figsize=(6, 4), dpi=100) self.figura.patch.set_facecolor("#becbff") self.sistema_ejes = self.figura.add_subplot(1, 1, 1) self.sistema_ejes.set_facecolor("#dee1ec") self.limpiar_ejes() self.canvas = FigureCanvasTkAgg(self.figura, master=self.label_grafica) self.canvas.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=True) toolbar = NavigationToolbar2Tk(self.canvas, self.frame_toolbar) toolbar.update() def limpiar_ejes(self): self.sistema_ejes.cla() self.sistema_ejes.set_xlabel('Tiempo (s)') self.sistema_ejes.set_ylabel('Nivel (dB)') self.sistema_ejes.set_xlim(left=0, auto=True) self.sistema_ejes.set_ylim(bottom=-120, top=0, auto=True) def construir_frame_medicion(self): self.frame_medicion = Frame(self.tab_frame) self.frame_medicion.grid(row=0, column=1, rowspan=2, sticky="nsew") self.construir_frame_bandas() def construir_frame_bandas(self): self.construir_seleccion_banda() self.construir_frame_rts() def construir_seleccion_banda(self): self.frame_titulo_bandas = Label(self.frame_medicion) self.frame_titulo_bandas.config(borderwidth=2, relief="groove") self.frame_titulo_bandas.grid(row=0, column=0, sticky="nsew", padx=10, pady=(15, 0)) self.label_titulo_bandas_octava = Label(self.frame_titulo_bandas) self.label_titulo_bandas_octava.config(text=self.titulo_bandas_text, bg="#0c005a") self.label_titulo_bandas_octava.pack(ipadx=10, expand="True", fill="both") self.frame_medicion_bandas = Frame(self.frame_medicion) self.frame_medicion_bandas.grid(row=1, column=0, sticky="nsew", padx=10, pady=(20, 0)) bandas_estandar = self.obtener_bandas() self.banda_seleccionada = StringVar() self.banda_seleccionada.set(bandas_estandar[0]) self.combobox_banda = OptionMenu(self.frame_medicion_bandas, self.banda_seleccionada, *bandas_estandar) self.combobox_banda.config(relief="groove", borderwidth=0, bg="#5893d4", activebackground="#0060ca", width=20) self.combobox_banda['menu'].config(bg="#5893d4", activebackground="#0060ca") self.combobox_banda.grid(row=0, column=0, padx=10) self.ponderacion_A_checked = BooleanVar(False) self.checkbutton_ponderacion_A = Checkbutton( self.frame_medicion_bandas) self.checkbutton_ponderacion_A.config( text="Ponderación A", variable=self.ponderacion_A_checked, selectcolor="#5e0606") self.checkbutton_ponderacion_A.grid(row=0, column=1, padx=20) self.boton_calcular = Button(self.frame_medicion_bandas) self.boton_calcular.config(text="Calcular", command=self.view.on_calcular, bg="#5e0606", width=20) self.boton_calcular.grid(row=0, column=2, padx=10) def construir_frame_rts(self): self.frame_rts = Frame(self.frame_medicion) self.frame_rts.config(borderwidth=2, relief='ridge') self.frame_rts.grid(row=4, column=0, padx=10, pady=(15, 0)) self.frame_titulo_rts = Label(self.frame_rts) self.frame_titulo_rts.config(borderwidth=2, relief="groove") self.frame_titulo_rts.grid(row=0, column=0, sticky="nsew", padx=10, pady=10, columnspan=2) self.label_titulo_rts = Label(self.frame_titulo_rts) self.label_titulo_rts.config(text="Tiempos de reverberación", bg="#0c005a") self.label_titulo_rts.pack(ipadx=10, expand="True", fill="both") self.frame_titulo_linealidad = Label(self.frame_rts) self.frame_titulo_linealidad.config(borderwidth=2, relief="groove") self.frame_titulo_linealidad.grid(row=0, column=2, sticky="nsew", padx=10, pady=10, columnspan=4) self.label_titulo_linealidad = Label(self.frame_titulo_linealidad) self.label_titulo_linealidad.config(text="Parámetros de linealidad", bg="#0c005a") self.label_titulo_linealidad.pack(ipadx=10, expand="True", fill="both") self.construir_frame_edt() self.construir_frame_t20() self.construir_frame_t30() self.construir_frame_curvatura() self.construir_frame_progressbar() def construir_frame_edt(self): self.frame_edt = Frame(self.frame_rts) self.frame_edt.grid(row=1, column=0, pady=(0, 10), columnspan=2) self.label_edt = Label(self.frame_edt) self.label_edt.config(text="EDT", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_edt.grid(row=0, column=0, padx=(0, 10), pady=10) self.edt_var = StringVar() self.label_res_edt = Label(self.frame_edt) self.label_res_edt.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.edt_var, fg="black") self.label_res_edt.grid(row=0, column=1, padx=(10, 0), pady=10) self.frame_linealidad_edt = Frame(self.frame_rts) self.frame_linealidad_edt.grid(row=1, column=2, pady=(0, 10), columnspan=4) self.label_r_edt = Label(self.frame_linealidad_edt) self.label_r_edt.config(text="r", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_r_edt.grid(row=0, column=0, padx=10, pady=10) self.r_edt_var = StringVar() self.label_res_r_edt = Label(self.frame_linealidad_edt) self.label_res_r_edt.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.r_edt_var, fg="black") self.label_res_r_edt.grid(row=0, column=1, padx=10, pady=10) self.label_xi_edt = Label(self.frame_linealidad_edt) self.label_xi_edt.config(text="ξ", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_xi_edt.grid(row=0, column=2, padx=10, pady=10) self.xi_edt_var = StringVar() self.label_res_xi_edt = Label(self.frame_linealidad_edt) self.label_res_xi_edt.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, fg="black", textvariable=self.xi_edt_var) self.label_res_xi_edt.grid(row=0, column=3, padx=10, pady=10) def construir_frame_t20(self): self.frame_t20 = Frame(self.frame_rts) self.frame_t20.grid(row=2, column=0, pady=(0, 10), columnspan=2) self.label_t20 = Label(self.frame_t20) self.label_t20.config(text="T20", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_t20.grid(row=0, column=0, padx=(0, 10), pady=10, sticky='w') self.t20_var = StringVar() self.label_res_t20 = Label(self.frame_t20) self.label_res_t20.config(relief="sunken", borderwidth=2, bg="#becbff", width=10, textvariable=self.t20_var, fg='black') self.label_res_t20.grid(row=0, column=1, padx=(10, 0), pady=10, sticky='e') self.frame_linealidad_t20 = Frame(self.frame_rts) self.frame_linealidad_t20.grid(row=2, column=2, pady=(0, 10), columnspan=4) self.label_r_t20 = Label(self.frame_linealidad_t20) self.label_r_t20.config(text="r", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_r_t20.grid(row=0, column=2, padx=10, pady=10) self.r_t20_var = StringVar() self.label_res_r_t20 = Label(self.frame_linealidad_t20) self.label_res_r_t20.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.r_t20_var, fg='black') self.label_res_r_t20.grid(row=0, column=3, padx=10, pady=10) self.label_xi_t20 = Label(self.frame_linealidad_t20) self.label_xi_t20.config(text="ξ", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_xi_t20.grid(row=0, column=4, padx=10, pady=10) self.xi_t20_var = StringVar() self.label_res_xi_t20 = Label(self.frame_linealidad_t20) self.label_res_xi_t20.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, fg='black', textvariable=self.xi_t20_var) self.label_res_xi_t20.grid(row=0, column=5, padx=10, pady=10) def construir_frame_t30(self): self.frame_t30 = Frame(self.frame_rts) self.frame_t30.grid(row=3, column=0, pady=(0, 10), columnspan=2) self.label_t30 = Label(self.frame_t30) self.label_t30.config(text="T30", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_t30.grid(row=0, column=0, padx=(0, 10), pady=10, sticky='w') self.t30_var = StringVar() self.label_res_t30 = Label(self.frame_t30) self.label_res_t30.config(relief="sunken", borderwidth=2, bg="#becbff", width=10, textvariable=self.t30_var, fg='black') self.label_res_t30.grid(row=0, column=1, padx=(10, 0), pady=10, sticky='e') self.frame_linealidad_t30 = Frame(self.frame_rts) self.frame_linealidad_t30.grid(row=3, column=2, pady=(0, 10), columnspan=4) self.label_r_t30 = Label(self.frame_linealidad_t30) self.label_r_t30.config(text="r", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_r_t30.grid(row=0, column=2, padx=10, pady=10) self.r_t30_var = StringVar() self.label_res_r_t30 = Label(self.frame_linealidad_t30) self.label_res_r_t30.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.r_t30_var, fg='black') self.label_res_r_t30.grid(row=0, column=3, padx=10, pady=10) self.label_xi_t30 = Label(self.frame_linealidad_t30) self.label_xi_t30.config(text="ξ", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_xi_t30.grid(row=0, column=4, padx=10, pady=10) self.xi_t30_var = StringVar() self.label_res_xi_t30 = Label(self.frame_linealidad_t30) self.label_res_xi_t30.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, fg='black', textvariable=self.xi_t30_var) self.label_res_xi_t30.grid(row=0, column=5, padx=10, pady=10) def construir_frame_curvatura(self): self.frame_curvatura = Frame(self.frame_rts) self.frame_curvatura.grid(row=4, column=2, pady=(0, 10), columnspan=4, sticky='e') self.label_curvatura = Label(self.frame_curvatura) self.label_curvatura.config(text="C", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_curvatura.grid(row=0, column=0, padx=(0, 10), pady=10, sticky='w') self.curvatura_var = StringVar() self.label_res_curvatura = Label(self.frame_curvatura) self.label_res_curvatura.config(relief="sunken", borderwidth=2, bg="#becbff", width=10, textvariable=self.curvatura_var, fg='black') self.label_res_curvatura.grid(row=0, column=1, padx=10, pady=10) def get_frecuencia_central_banda_seleccionada(self): return float(self.banda_seleccionada.get()) def get_tipo(self): return self.tipo def verificar_ponderacion_A(self): return self.ponderacion_A_checked.get() def desactivar(self): self.combobox_banda.config(state=DISABLED) self.checkbutton_ponderacion_A.config(state=DISABLED) self.boton_calcular.config(state=DISABLED) def activar(self): self.combobox_banda.config(state=NORMAL) self.checkbutton_ponderacion_A.config(state=NORMAL) self.boton_calcular.config(state=NORMAL) def graficar(self, nivel_respuesta_impulsional, curva_decaimiento): dominio_temporal_ri = nivel_respuesta_impulsional.get_dominio_temporal( ) valores_ri = nivel_respuesta_impulsional.get_valores() dominio_temporal_cd = curva_decaimiento.get_dominio_temporal() valores_cd = curva_decaimiento.get_valores() self.limpiar_ejes() self.sistema_ejes.plot(dominio_temporal_ri, valores_ri, color='#0000ff', linewidth=0.5, label='Nivel respuesta impulsional') self.sistema_ejes.plot(dominio_temporal_cd, valores_cd, color="#ff0000", linewidth=1, label='Curva de decaimiento') self.sistema_ejes.legend() self.canvas.draw() def mostrar_tiempos_de_reverberacion(self, edt, t20, t30): self.edt_var.set(str(round(edt, 4)) + "seg") self.t20_var.set(str(round(t20, 4)) + "seg") self.t30_var.set(str(round(t30, 4)) + "seg") def mostrar_parametros_de_linealidad(self, edt, t20, t30, curvatura): self.r_edt_var.set(round(edt.get_coef_correlacion(), 4)) self.xi_edt_var.set(str(round(edt.get_xi(), 4)) + "‰") self.r_t20_var.set(round(t20.get_coef_correlacion(), 4)) self.xi_t20_var.set(str(round(t20.get_xi(), 4)) + "‰") self.r_t30_var.set(round(t30.get_coef_correlacion(), 4)) self.xi_t30_var.set(str(round(t30.get_xi(), 4)) + "‰") self.curvatura_var.set(str(round(curvatura, 4)) + "%") def construir_frame_progressbar(self): self.pb_frame = Frame(self.frame_medicion) self.pb_frame.config(padx=20, pady=20) self.frame_calculando = Frame(self.pb_frame) self.frame_calculando.grid(row=0, column=0, pady=10) self.label_calculando = Label(self.frame_calculando) self.label_calculando.config(text="Calculando") self.label_calculando.pack(expand="True", fill="both") self.progressbar = Progressbar(self.pb_frame) self.progressbar.config(mode="indeterminate", length=250) self.progressbar.grid(row=1, column=0, pady=10) def activar_progressbar(self): self.pb_frame.grid(row=5, column=0) self.progressbar.start(10) def desactivar_progressbar(self): self.progressbar.stop() self.pb_frame.grid_remove() def redibujar_canvas(self): self.canvas.draw() self.canvas.get_tk_widget().pack() def ocultar_grafica(self): self.canvas.get_tk_widget().pack_forget()
class DemoClient(Frame): def __init__(self, tk, args): Frame.__init__(self, tk) locale.setlocale(locale.LC_ALL, '') # empty string for platform's default settings self.master = tk self.config = json.load(open('config.json', 'r')) self.config['COMBOBOX_INDEX'] = sorted(self.config['COMBOBOX_INDEX'], key=lambda x: x[0]) self.game_type = int( args.gametype ) if args.gametype else self.config["DEFAULT_GAME_TYPE_ID"] tk.title(self.config["APP_TITLE"]) tk.resizable(False, False) self.get_icon() atexit.register(self.cancel_game) # Init class data fields that we use for storing info that we need for using the API self.bot_id = None self.bot_password = None self.logged_in = False self.game_style_ids = [] self.gameChips = 0 self.gameDeals = 0 self.gameStake = 0 self.gamePrize = 0 self.player_key = None self.play_again = BooleanVar() self.do_not_play_same_user = BooleanVar() self.close_after_game = False self.game_cancelled = False self.in_game = False self.topFrame = Frame(tk, padx=12, pady=12) self.middleFrame = Frame(tk, padx=12) self.middleFrameLeft = Frame(self.middleFrame) self.middleFrameRight = Frame(self.middleFrame) self.middleFrameRighter = Frame(self.middleFrame) self.topFrame.grid(row=0, sticky=W + E) self.middleFrame.grid(row=1, sticky=W) self.middleFrameLeft.grid(row=1, column=0) self.middleFrameRight.grid(row=1, column=1) self.middleFrameRighter.grid(row=1, column=2) # =================================== # Create form elements # Top Frame Elements self.botNameLabel = Label(self.topFrame, text="Bot Name:") self.bot_id_entry = Entry(self.topFrame) self.bot_id_entry.bind('<Return>', self.log_in_if_not) self.bot_id_entry.focus() self.passwordLabel = Label(self.topFrame, text="Password:"******"Login", command=self.log_in_out_clicked) self.balanceLabel = Label(self.topFrame, text="Bot Balance:") self.balance = Label(self.topFrame, text="0") self.close_button = Button(self.topFrame, text="Close", padx=2, command=tk.destroy) # Middle Frame Elements # Middle Frame LEFT Elements self.gameTypeCmb = ttk.Combobox( self.middleFrameLeft, state="disabled", values=tuple((game[0]) for game in self.config['COMBOBOX_INDEX'])) if self.game_type != self.config['NULL_GAME_TYPE_ID']: index = [ i for i in range(len(self.config['COMBOBOX_INDEX'])) if self.config['COMBOBOX_INDEX'][i][1] == self.game_type ][0] self.gameTypeCmb.current( index) # Default selection matches default game type id self.gameTypeCmb.bind("<<ComboboxSelected>>", self.game_type_selected) self.gameStyleLabel = Label(self.middleFrameLeft, font=(None, 18), pady=0, text="Game Style Selection") self.opponentLabel = Label(self.middleFrameLeft, text="Specify Opponent (optional):") self.specify_opponent_cmb = ttk.Combobox( self.middleFrameLeft, values=self.config['AVAILABLE_OPPONENTS']) self.do_not_play_same_user_check = Checkbutton( self.middleFrameLeft, text='Don\'t play another bot in same user account as me', var=self.do_not_play_same_user) self.game_styles_listbox = Listbox(self.middleFrameLeft, background='#FFFFFF', height=8) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind( '<Return>', self.find_game_double_clicked ) # Not a double click but we want it to do the same thing self.refresh_game_styles_button = Button( self.middleFrameLeft, text="Refresh Game Styles", command=self.refresh_game_styles_clicked) self.thinkingTimeLabel = Label(self.middleFrameLeft, text="Add \"Thinking Time\" (ms):") self.thinking_time_entry = Entry(self.middleFrameLeft) self.auto_play_next_game_check = Checkbutton( self.middleFrameLeft, text='Play another game when complete', var=self.play_again) self.cancel_stop_game_button = Button( self.middleFrameLeft, text=CANCEL_GAME_TEXT, command=self.cancel_stop_game_clicked) self.find_game_button = Button(self.middleFrameLeft, text="Find Game", command=self.find_game_clicked) self.resultText = Message( self.middleFrameLeft, width=300, text="This is where the informational messages will appear") self.spacerLabel = Label(self.middleFrameLeft, text=" ") # Middle Frame RIGHT Elements self.gameTitleLabel = Label(self.middleFrameRight, text="Game Title") self.gameTitleText = Text(self.middleFrameRight, height=3, background='white', spacing1=3, pady=0) self.player = None # Initialise as none before updating in create_visuals() self.opponent = None # Initialise as none before updating in create_visuals() self.create_visuals() self.gameActionLabel = Label(self.middleFrameRight, text="") # =================================== # Set initial element states self.set_gamestyle_controls_states(DISABLED) self.cancel_stop_game_button.config(state=DISABLED) self.game_styles_listbox.config(background='white') self.thinking_time_entry.insert(0, 100) self.gameTitleText.config(state=DISABLED) self.set_balance(0) self.gameTitleText.tag_configure("center", justify='center') self.gameTitleText.tag_configure("bold", font='-weight bold') # =================================== # Form Layout # Top Frame Form Layout self.topFrame.grid_rowconfigure(0, weight=1) self.botNameLabel.grid(row=0, column=0, sticky=E) self.bot_id_entry.grid(row=0, column=1, sticky=W) self.passwordLabel.grid(row=0, column=2, sticky=E) self.bot_password_entry.grid(row=0, column=3, sticky=W) self.log_in_out_button.grid(row=0, column=4, sticky=E) self.topFrame.grid_columnconfigure(5, weight=1) self.balanceLabel.grid(row=0, column=5, sticky=E) self.balance.grid(row=0, column=6, sticky=W) self.close_button.grid(row=0, column=7, sticky=E, padx=(50, 0)) # Middle Frame Form Layout self.middleFrame.grid_rowconfigure(0, weight=1) self.gameTypeCmb.grid(row=0, column=0, columnspan=1, sticky=W + E) self.gameStyleLabel.grid(row=1, column=0, columnspan=1, sticky=W + E) self.spacerLabel.grid(row=1, column=2, sticky=E) self.opponentLabel.grid(row=2, column=0, sticky=W, pady=4) self.specify_opponent_cmb.grid(row=2, column=0, sticky=E, pady=4) self.do_not_play_same_user_check.grid(row=3, column=0, columnspan=1, sticky='we', pady=4) self.game_styles_listbox.grid(row=4, column=0, columnspan=1, sticky='we', pady=4) self.find_game_button.grid(row=5, column=0, pady=4, sticky=W) self.refresh_game_styles_button.grid(row=5, column=0, columnspan=1, sticky='', pady=4) self.cancel_stop_game_button.grid(row=5, column=0, sticky=E) self.thinkingTimeLabel.grid(row=6, column=0, sticky=W, pady=4) self.thinking_time_entry.grid(row=6, column=0, sticky=E, pady=4) self.auto_play_next_game_check.grid(row=7, column=0, columnspan=1, sticky=W, pady=4) self.resultText.grid(row=9, column=0, columnspan=2, sticky=W, pady=4) self.middleFrame.grid_columnconfigure(9, weight=1) self.gameTitleLabel.grid(row=0, column=3) self.gameTitleText.grid(row=0, column=3, columnspan=2) self.gameActionLabel.grid(row=11, column=3, sticky='w') if args.botid is not None and args.password is not None: self.auto_play(args) def auto_play(self, args): self.bot_id_entry.insert(0, args.botid) self.bot_password_entry.insert(0, args.password) self.log_in_out_clicked() self.thinking_time_entry.insert(0, args.timeout) if args.playanothergame: self.auto_play_next_game_check.select() if args.dontplaysameuserbot: self.do_not_play_same_user_check.select() if args.closeaftergame: self.close_after_game = True if args.gamestyle is not None: i = 0 for i in range(self.game_styles_listbox.size()): if args.gamestyle in str(self.game_styles_listbox.get(i)): break self.game_styles_listbox.select_set(i, i) self.find_game_clicked() def log_in_out_clicked(self): """Click handler for the 'Login'/'Logout' button.""" # This means we're logging out if self.logged_in: self.resultText.config(text='Logged Out') self.master.title(self.config["APP_TITLE"] + " (Not Logged In)") self.cancel_game() self.bot_id = None self.bot_password = None self.clear_game_title_text() self.gameActionLabel.config(text="") self.reset_game_styles_listbox() self.clear_all_boards() self.opponent.delete("all") self.log_in_out_button.config(text='Login') self.set_login_controls_states(ENABLED) self.set_gamestyle_controls_states(DISABLED) self.gameTypeCmb.config(state="disabled") self.logged_in = False self.bot_password_entry.delete(0, 'end') self.set_balance(0) # This means we're logging in else: self.bot_id = self.bot_id_entry.get() self.bot_password = self.bot_password_entry.get() res = self.get_list_of_game_styles() if res['Result'] == 'SUCCESS': self.resultText.config(text='Logged In') game_styles = res['GameStyles'] self.master.title(self.bot_id + " - " + self.config["APP_TITLE"]) self.set_login_controls_states(DISABLED) self.set_gamestyle_controls_states(ENABLED) self.gameTypeCmb.config(state="readonly") self.set_game_styles_listbox(game_styles) self.set_balance(res['Balance']) self.log_in_out_button.config(text='Logout') self.logged_in = True else: messagebox.showerror( 'Error', 'Invalid login attempt. Please check the username and password entered.' ) def log_in_if_not(self, _): if not self.logged_in: self.log_in_out_clicked() def clear_all_boards(self): self.player.clear_board() self.opponent.clear_board() self.player.delete("all") self.opponent.delete("all") self.player.myBoard = None self.opponent.oppBoard = None def set_in_game(self, value): self.in_game = value def set_game_title_text(self, text, tag): self.gameTitleText.config(state=ENABLED) self.gameTitleText.insert("end", text, ("center", tag)) self.gameTitleText.config(state=DISABLED) def clear_game_title_text(self): self.gameTitleText.config(state=ENABLED) self.gameTitleText.delete("1.0", "end") self.gameTitleText.config(state=DISABLED) def set_login_controls_states(self, state): self.bot_id_entry.config(state=state) self.bot_password_entry.config(state=state) def set_gamestyle_controls_states(self, state): self.specify_opponent_cmb.config(state=state) self.do_not_play_same_user_check.config(state=state) self.game_styles_listbox.config(state=state) self.find_game_button.config(state=state) self.refresh_game_styles_button.config(state=state) self.auto_play_next_game_check.config(state=state) self.thinking_time_entry.config(state=state) self.opponentLabel.config(state=state) self.thinkingTimeLabel.config(state=state) self.balanceLabel.config(state=state) self.balance.config(state=state) self.gameStyleLabel.config(state=state) self.game_styles_listbox.config(state=state) self.player.config(state=state) self.opponent.config(state=state) def set_balance(self, balance): """Set the balance field""" self.balance['text'] = int_with_commas(balance) def get_list_of_game_styles(self): """Get list of game styles from the server.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'GameTypeId': self.game_type } url = self.config["BASE_URL"] + self.config[ "GET_LIST_OF_GAME_STYLES_EXTENSION"] return DemoClient.make_api_call(url, req) def set_game_styles_listbox(self, game_styles): """Set the content of the game styles listbox with a list of GameStyle dictionaries. Keyword Arguments: game_styles -- The list of GameStyle dictionaries, this should be obtained through get_list_of_game_styles(). """ self.reset_game_styles_listbox() for index, game_style in enumerate(game_styles): if self.game_type == self.config["BATTLESHIPS_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["BATTLESHIPS_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Ships'], game_style['GameTypeSpecificInfo']['Board Size'], game_style['GameTypeSpecificInfo']['Timeout ms'], game_style['GameTypeSpecificInfo']['DealsTotal'], game_style['GameTypeSpecificInfo']['PercentageLand'], game_style['GameTypeSpecificInfo']['RandomLand'])) elif self.game_type == self.config[ "NOUGHTS_AND_CROSSES_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["NOUGHTS_AND_CROSSES_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['DealsTotal'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config[ "TRAVELLING_SALESDRONE_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self. config["TRAVELLING_SALESDRONE_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['TotalCities'], game_style['GameTypeSpecificInfo']['DealLength'])) elif self.game_type == self.config["PREDICTIVE_TEXT_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self. config["PREDICTIVE_TEXT_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo'] ['Number of Sentences'], game_style['GameTypeSpecificInfo'] ['Switched Words Game'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["TWIST_CUBE_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["TWIST_CUBE_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['cubeSize'], game_style['GameTypeSpecificInfo']['GameLength'])) elif self.game_type == self.config["SLIDING_PUZZLE_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["SLIDING_PUZZLE_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['RowSize'], game_style['GameTypeSpecificInfo']['ColumnSize'], game_style['GameTypeSpecificInfo']['TimeLimit'])) elif self.game_type == self.config["BLURRY_WORD_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["BLURRY_WORD_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['NumImages'], game_style['GameTypeSpecificInfo']['GameLength'])) elif self.game_type == self.config["MASTERMIND_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["MASTERMIND_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['NumPegs'], game_style['GameTypeSpecificInfo']['NumColours'], game_style['GameTypeSpecificInfo'] ['DuplicatesAllowed'])) elif self.game_type == self.config[ "WAREHOUSE_LOGISTICS_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["WAREHOUSE_LOGISTICS_GAME_STYLE_LISTBOX_TEXT"]. format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo'] ['WarehouseDimensions'][0], game_style['GameTypeSpecificInfo'] ['WarehouseDimensions'][1])) elif self.game_type == self.config["FOUR_IN_A_ROW_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["FOUR_IN_A_ROW_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['Connections'])) elif self.game_type == self.config["WHO_IS_WHO_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["WHO_IS_WHO_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['NumCharacters'], game_style['GameTypeSpecificInfo']['ComparisonRound'])) elif self.game_type == self.config[ "REVERSING_STONES_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["REVERSING_STONES_GAME_STYLE_LISTBOX_TEXT"]. format(game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['Holes'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["CHECKERS_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["CHECKERS_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["GO_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["GO_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], "CAPTURE" if game_style['GameTypeSpecificInfo']['IsCaptureGo'] else game_style['GameTypeSpecificInfo']['ScoringMethod'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["LEXICO_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["LEXICO_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['Dimensions'][0], game_style['GameTypeSpecificInfo']['Dimensions'][1], game_style['GameTypeSpecificInfo']['TileMultipliers'], game_style['GameTypeSpecificInfo']['Timeout ms'])) elif self.game_type == self.config["DOMINOES_GAME_TYPE_ID"]: self.game_styles_listbox.insert( index, self.config["DOMINOES_GAME_STYLE_LISTBOX_TEXT"].format( game_style['GameStyleId'], game_style['Stake'], game_style['GameTypeSpecificInfo']['SpotNo'], game_style['GameTypeSpecificInfo']['Timeout ms'])) else: raise ValueError('INVALID GAME TYPE PARAMETER') self.game_style_ids.append(game_style['GameStyleId']) # self.game_styles_listbox.select_set(GAME_STYLE_LISTBOX_DEFAULT_SELECTION) def reset_game_styles_listbox(self): """Clear the content of the game styles listbox.""" if self.game_styles_listbox.size() != 0: self.game_styles_listbox.delete(0, 'end') self.game_style_ids = [] def refresh_game_styles_clicked(self): """Click handler for the 'Refresh Game Styles' button.""" res = self.get_list_of_game_styles() game_styles = res['GameStyles'] self.set_game_styles_listbox(game_styles) def find_game_clicked(self): """Click handler for the 'Find Game' button""" self.find_game_button.config(state=DISABLED) self.cancel_stop_game_button.config(state=ENABLED) self.game_styles_listbox.unbind('<Double-1>') self.game_styles_listbox.unbind('<Return>') self.game_styles_listbox.config(state=DISABLED) self.clear_all_boards() # Here we dispatch the work to a separate thread, to keep the GUI responsive. if not MAC: threading.Thread(target=self.game_loop, daemon=True).start() else: self.game_loop() # Doesn't work on MACs def find_game_double_clicked(self, _): self.find_game_clicked() def game_type_selected(self, _): self.game_type = self.config["COMBOBOX_INDEX"][ self.gameTypeCmb.current()][1] res = self.get_list_of_game_styles() if res['Result'] == 'SUCCESS': game_styles = res['GameStyles'] self.set_game_styles_listbox(game_styles) self.get_icon() self.player.destroy() self.opponent.destroy() self.create_visuals() def get_icon(self): try: if WINDOWS: self.master.iconbitmap("assets/{0}/icon.ico".format( self.game_type)) else: self.master.iconbitmap("./assets/{0}/icon.xbm".format( self.game_type)) except Exception as e: print(e) def create_visuals(self): if self.game_type == self.config["NULL_GAME_TYPE_ID"]: self.player = null_visuals.NullVisuals( self.middleFrameRight) # Game Display Table self.opponent = null_visuals.NullVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["BATTLESHIPS_GAME_TYPE_ID"]: self.player = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table self.opponent = battleships_visuals.BattleshipsVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["NOUGHTS_AND_CROSSES_GAME_TYPE_ID"]: self.player = noughts_and_crosses_visuals.NoughtsAndCrossesVisuals( self.middleFrameRight) # Game Display Table self.opponent = noughts_and_crosses_visuals.NoughtsAndCrossesVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config[ "TRAVELLING_SALESDRONE_GAME_TYPE_ID"]: self.player = travelling_salesdrone_visuals.TravellingSalesdroneVisuals( self.middleFrameRight) # Game Display Table self.opponent = travelling_salesdrone_visuals.TravellingSalesdroneVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["PREDICTIVE_TEXT_GAME_TYPE_ID"]: self.player = predictive_text_visuals.PredictiveTextVisuals( self.middleFrameRight) # Game Display Table self.opponent = predictive_text_visuals.PredictiveTextVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["TWIST_CUBE_GAME_TYPE_ID"]: self.player = twist_cube_visuals.TwistCubeVisuals( self.middleFrameRight) # Game Display Table self.opponent = twist_cube_visuals.TwistCubeVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["SLIDING_PUZZLE_GAME_TYPE_ID"]: self.player = sliding_puzzle_visuals.SlidingPuzzleVisuals( self.middleFrameRight) # Game Display Table self.opponent = sliding_puzzle_visuals.SlidingPuzzleVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["BLURRY_WORD_GAME_TYPE_ID"]: self.player = blurry_word_visuals.MicrosoftCognitiveChallengeVisuals( self.middleFrameRight) # Game Display Table self.opponent = blurry_word_visuals.MicrosoftCognitiveChallengeVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["MASTERMIND_GAME_TYPE_ID"]: self.player = mastermind_visuals.MastermindVisuals( self.middleFrameRight) # Game Display Table self.opponent = mastermind_visuals.MastermindVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["WAREHOUSE_LOGISTICS_GAME_TYPE_ID"]: self.player = warehouse_logistics_visuals.WarehouseLogisticsVisuals( self.middleFrameRight) # Game Display Table self.opponent = warehouse_logistics_visuals.WarehouseLogisticsVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["FOUR_IN_A_ROW_GAME_TYPE_ID"]: self.player = four_in_a_row_visuals.FourInARowVisuals( self.middleFrameRight) # Game Display Table self.opponent = four_in_a_row_visuals.FourInARowVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["WHO_IS_WHO_GAME_TYPE_ID"]: self.player = who_is_who_visuals.WhoIsWhoVisuals( self.middleFrameRight) # Game Display Table self.opponent = who_is_who_visuals.WhoIsWhoVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["REVERSING_STONES_GAME_TYPE_ID"]: self.player = reversing_stones_visuals.ReversingStonesVisuals( self.middleFrameRight) # Game Display Table self.opponent = reversing_stones_visuals.ReversingStonesVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["CHECKERS_GAME_TYPE_ID"]: self.player = checkers_visuals.CheckersVisuals( self.middleFrameRight) # Game Display Table self.opponent = checkers_visuals.CheckersVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["GO_GAME_TYPE_ID"]: self.player = go_visuals.GoVisuals( self.middleFrameRight) # Game Display Table self.opponent = go_visuals.GoVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["LEXICO_GAME_TYPE_ID"]: self.player = lexico_visuals.LexicoVisuals( self.middleFrameRight) # Game Display Table self.opponent = lexico_visuals.LexicoVisuals( self.middleFrameRight) # Game Display Table elif self.game_type == self.config["DOMINOES_GAME_TYPE_ID"]: self.player = dominoes_visuals.DominoesVisuals( self.middleFrameRight) # Game Display Table self.opponent = dominoes_visuals.DominoesVisuals( self.middleFrameRight) # Game Display Table else: raise ValueError('INVALID GAME TYPE PARAMETER') self.player.grid(row=1, column=3) self.opponent.grid(row=1, column=4) def game_loop(self): """Loop through finding and playing games.""" while True: self.clear_all_boards() mover.persistentData = {} self.find_game() self.update_balance() if self.game_cancelled: break self.play_game() self.update_balance() if self.close_after_game: self.close_button.invoke() if self.game_cancelled: break if not self.play_again.get(): break self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind('<Return>', self.find_game_double_clicked) self.game_styles_listbox.config(state=ENABLED) self.game_cancelled = False def find_game(self): """Find a game.""" offer_game_res = self.offer_game() if offer_game_res['Result'] == 'INVALID_LOGIN_OR_PASSWORD': self.cancel_stop_game_clicked() if 'ErrorMessage' in offer_game_res and offer_game_res[ 'ErrorMessage'] == 'Check of OpponentId failed': self.resultText.config(text='Invalid Opponent ID') else: self.resultText.config(text='Invalid login or password') elif offer_game_res['Result'] == 'INSUFFICIENT_BALANCE': self.cancel_stop_game_clicked() self.resultText.config(text='Insufficient balance') elif offer_game_res['Result'] == 'BOT_IS_INACTIVE': self.cancel_stop_game_clicked() self.resultText.config(text='Bot is inactive') else: self.player_key = offer_game_res['PlayerKey'] if offer_game_res['Result'] == 'WAITING_FOR_GAME': self.wait_for_game() def offer_game(self): """Offer a game.""" self.cancel_game( ) # Cancel the last outstanding game offer that was made opponent_id = self.specify_opponent_cmb.get() if len(opponent_id) == 0: opponent_id = None try: game_style_id = self.game_style_ids[int( self.game_styles_listbox.curselection()[0])] except IndexError: self.game_styles_listbox.select_set( GAME_STYLE_LISTBOX_DEFAULT_SELECTION) game_style_id = self.game_style_ids[0] req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'GameStyleId': game_style_id, 'DontPlayAgainstSameUser': self.do_not_play_same_user.get(), 'DontPlayAgainstSameBot': False, 'OpponentId': opponent_id } url = self.config["BASE_URL"] + self.config["OFFER_GAME_EXTENSION"] return DemoClient.make_api_call(url, req) def wait_for_game(self): """Wait for game to start.""" self.resultText.config(text='Waiting for game') while True: if self.game_cancelled: self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind('<Return>', self.find_game_double_clicked) self.game_styles_listbox.config(state=ENABLED) break poll_results = self.poll_for_game_state() if poll_results['Result'] == 'SUCCESS': break if poll_results['Result'] == 'INVALID_PLAYER_KEY' or poll_results[ 'Result'] == 'GAME_HAS_ENDED' or poll_results[ 'Result'] == 'GAME_WAS_STOPPED': self.game_cancelled = True time.sleep(2) def play_game(self): """Play a game.""" self.resultText.config(text='Playing game') self.in_game = True poll_results = self.poll_for_game_state() if poll_results["Result"] != "SUCCESS": return game_state = poll_results['GameState'] title = format('Game ID: ' + str(game_state['GameId'])) title += format(' / Style: ' + str(self.game_style_ids[int( self.game_styles_listbox.curselection()[0])])) title += "\n" versus = format(self.bot_id + ' vs ' + game_state['OpponentId']) self.clear_game_title_text() self.set_game_title_text(title, "") self.set_game_title_text(versus, "bold") self.middleFrame.update() while True: if self.game_cancelled: break if game_state['IsMover']: self.resultText.config(text='Playing Game - Your Turn') move = mover.calculate_move(self.game_type, game_state) move_results = self.make_move(move) if move_results['Result'] == 'INVALID_MOVE': self.resultText.config(text="Invalid Move") elif move_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + move_results['Result']) print(str(move_results)) print("Game ended") break else: game_state = move_results['GameState'] else: self.resultText.config(text="Playing Game - Opponent's Turn") # ---- Code here will be called on your opponent's turn ---- # ---------------------------------------------------------- poll_results = self.poll_for_game_state() if poll_results['Result'] != 'SUCCESS': self.resultText.config(text='Game has ended: ' + poll_results['Result']) break game_state = poll_results['GameState'] if game_state['GameStatus'] != 'RUNNING': break self.middleFrameRight.update() try: if int(self.thinking_time_entry.get()) > 0: time.sleep((int(self.thinking_time_entry.get()) / 1000)) else: time.sleep(0.1) except ValueError: time.sleep(0.1) self.set_in_game(False) def make_move(self, move): """Make a move.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key, 'Move': move } url = self.config["BASE_URL"] + self.config["MAKE_MOVE_EXTENSION"] result = DemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: print(result) try: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) except Exception as e: print("Gamestate error: " + str(e)) return result def poll_for_game_state(self): """Poll the server for the latest GameState.""" req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'MaximumWaitTime': 1000, 'PlayerKey': self.player_key } url = self.config["BASE_URL"] + self.config[ "POLL_FOR_GAME_STATE_EXTENSION"] result = DemoClient.make_api_call(url, req) if result['Result'] == 'SUCCESS' or "GAME_HAS_ENDED" in result[ 'Result']: self.player.draw_game_state(result['GameState'], True) self.opponent.draw_game_state(result['GameState'], False) return result def cancel_stop_game_clicked(self): self.game_cancelled = True self.cancel_game() self.find_game_button.config(state=ENABLED) self.cancel_stop_game_button.config(state=DISABLED, text=CANCEL_GAME_TEXT) self.game_styles_listbox.bind('<Double-1>', self.find_game_double_clicked) self.game_styles_listbox.bind('<Return>', self.find_game_double_clicked) self.game_styles_listbox.config(state=ENABLED) def cancel_game(self): print("Cancelling last game offer") if self.player_key is None: return req = { 'BotId': self.bot_id, 'BotPassword': self.bot_password, 'PlayerKey': self.player_key } url = self.config["BASE_URL"] + self.config[ "CANCEL_GAME_OFFER_EXTENSION"] DemoClient.make_api_call(url, req) try: self.resultText.config(text='Cancelled game') except Exception as e: print(str(e) + " -- Demo client has been closed") def update_balance(self): res = self.get_list_of_game_styles() self.set_balance(res['Balance']) @staticmethod def make_api_call(url, req): """Make an API call.""" while True: try: res = requests.post(url, json=req, headers=API_CALL_HEADERS, timeout=60.0) try: jres = res.json() if 'Result' in jres: return jres time.sleep(0.1) except ValueError: time.sleep(0.1) except requests.ConnectionError: time.sleep(0.1) except requests.Timeout: time.sleep(0.1) except requests.HTTPError: time.sleep(0.1) except BaseException as e: # Bad code but needed for testing purposes print(e) time.sleep(0.1)
class Main: def __init__(self): self.master = Tk() self.master.wm_title("20 Combo Challenge") self.master.minsize(width=100,height=100) self.master.maxsize(width=1600,height=950) self.master.geometry('1048x863+860+80') main_font = ("Courier", 22, "bold") self.set_piece_marker = False self.on_builder = True board_frame = ttk.Frame(self.master) board_frame.grid(row=0,column=1,rowspan=20) self.display = TetrisDisplay(self.master, board_frame) self.handler = Build(self) self.make_canvas_interactive() self.board_set_index = 0 self.board_set = [self.handler.board] self.update_display() self.history_position = self.handler.board.history_depth - 1 # self.hold_entry = Entry(self.master,justify=LEFT,width=6) self.hold_entry.config(font=main_font) self.hold_entry.grid(row=2,column=0) # def add_blocks(): self.last_block_altered = None if self.remove_blocks_check.get() == 1: self.remove_blocks_check.set(0) self.add_blocks_check.set(1) self.add_blocks_check = IntVar() self.add_blocks_check.set(0) self.add_blocks_button = Checkbutton(self.master, text="Add", variable=self.add_blocks_check, command=add_blocks) self.add_blocks_button.config(font=main_font) self.add_blocks_button.grid(row=3, column=0, sticky='w') # def remove_blocks(): self.last_block_altered = None if self.add_blocks_check.get() == 1: self.add_blocks_check.set(0) self.remove_blocks_check.set(1) self.remove_blocks_check = IntVar() self.remove_blocks_check.set(0) self.remove_blocks_button = Checkbutton(self.master, text="Rem", variable=self.remove_blocks_check, command=remove_blocks) self.remove_blocks_button.config(font=main_font) self.remove_blocks_button.grid(row=4, column=0, sticky='w') # def clear_blocks(): self.handler.board.set_blocks[...] = 0 self.update_display() self.clear_blocks_button = Button(self.master,text="Clear\nBoard",command=clear_blocks) self.clear_blocks_button.config(font=main_font) self.clear_blocks_button.grid(row=10,column=0) ######## self.active_piece_entry = Entry(self.master,justify=LEFT,width=6) self.active_piece_entry.config(font=main_font) self.active_piece_entry.grid(row=0,column=2) # ttk.Separator(self.master, orient="horizontal").grid(row=1, column=2, sticky="ew") # self.queue1_entry = Entry(self.master,justify=LEFT,width=6) self.queue1_entry.config(font=main_font) self.queue1_entry.grid(row=2,column=2) # self.queue2_entry = Entry(self.master,justify=LEFT,width=6) self.queue2_entry.config(font=main_font) self.queue2_entry.grid(row=3,column=2) # self.queue3_entry = Entry(self.master,justify=LEFT,width=6) self.queue3_entry.config(font=main_font) self.queue3_entry.grid(row=4,column=2) # self.queue4_entry = Entry(self.master,justify=LEFT,width=6) self.queue4_entry.config(font=main_font) self.queue4_entry.grid(row=5,column=2) # self.update_button = Button(self.master,text="Update",command=self.update_pieces) self.update_button.config(font=main_font) self.update_button.grid(row=6,column=2) # def build_thread(): build_thread = multiprocessing.Process(target=self.build_it()) build_thread.daemon = True build_thread.start() self.build_button = Button(self.master,text="Build",command=build_thread) self.build_button.config(font=main_font) self.build_button.grid(row=7,column=2) # def break_thread(): break_thread = multiprocessing.Process(target=self.break_it()) break_thread.daemon = True break_thread.start() self.break_button = Button(self.master,text="Break",command=break_thread) self.break_button.config(font=main_font) self.break_button.grid(row=8,column=2) # def clear_piece(): self.handler.board.active_blocks[...] = 0 self.update_display() self.clear_piece_button = Button(self.master,text="Clear\nPiece",command=clear_piece) self.clear_piece_button.config(font=main_font) self.clear_piece_button.grid(row=9,column=2) # def make_columns(): random_fill = np.random.randint(1,7,self.handler.board.set_blocks.shape) self.handler.board.set_blocks[2:,:3]=random_fill[2:,:3] self.handler.board.set_blocks[2:,7:]=random_fill[2:,7:] self.update_display() self.make_columns_button = Button(self.master,text="Make\nColumns",command=make_columns) self.make_columns_button.config(font=main_font) self.make_columns_button.grid(row=10,column=2) # self.index_entry = Entry(self.master,justify=LEFT,width=6) self.index_entry.config(font=main_font,justify="center") self.index_entry.grid(row=11,column=2) self.index_entry.insert("end","0/0") self.index_entry.config(state="disabled") # history_buttons_frame = ttk.Frame(self.master) history_buttons_frame.grid(row=12,column=2) def history_back(): if self.board_set_index > 0: self.board_set_index -= 1 self.handler.board = self.board_set[self.board_set_index] self.update_index_entry() self.update_display() def history_forward(): if self.board_set_index < len(self.board_set)-1: self.board_set_index += 1 self.handler.board = self.board_set[self.board_set_index] self.update_index_entry() self.update_display() self.previous_button = Button(history_buttons_frame,text="<--",command=history_back) self.previous_button.config(font=main_font) self.previous_button.pack(side="left") self.next_button = Button(history_buttons_frame,text="-->",command=history_forward) self.next_button.config(font=main_font) self.next_button.pack(side="right") # self.resize_CLI_window() mainloop() def make_canvas_interactive(self): self.last_block_altered = None def callback(event): if self.add_blocks_check.get() or self.remove_blocks_check.get(): block_location = (int(event.y / self.display.block_size),int(event.x / self.display.block_size)) if block_location in self.display.main_board_blocks: board_location = list(block_location) board_location[1] = board_location[1] - self.display.columns_left_of_game if self.add_blocks_check.get() and board_location != self.last_block_altered: if self.handler.board.active_blocks[board_location[0],board_location[1]] == 0: self.handler.board.set_blocks[board_location[0],board_location[1]]=randint(-7,-1) self.update_display() self.last_block_altered = board_location if self.remove_blocks_check.get() and board_location != self.last_block_altered: self.handler.board.set_blocks[board_location[0],board_location[1]]=0 self.update_display() self.last_block_altered = board_location self.display.the_canvas.bind("<Button-1>", callback) self.display.the_canvas.bind("<B1-Motion>", callback) def update_display(self): self.display.hold_box_update(self.handler.board.held_piece) self.display.queue_images_update(self.handler.board.piece_queue) self.display.refresh_screen(self.handler.board.board_snapshot()) def state_change(self,state): self.hold_entry.config(state=state) self.active_piece_entry.config(state=state) self.queue1_entry.config(state=state) self.queue2_entry.config(state=state) self.queue3_entry.config(state=state) self.queue4_entry.config(state=state) self.build_button.config(state=state) self.break_button.config(state=state) self.clear_piece_button.config(state=state) self.previous_button.config(state=state) self.next_button.config(state=state) self.add_blocks_button.config(state=state) self.remove_blocks_button.config(state=state) self.clear_blocks_button.config(state=state) self.update_button.config(state=state) self.make_columns_button.config(state=state) if state == "disabled": if self.add_blocks_check.get() == 1: self.add_blocks_check.set(0) if self.remove_blocks_check.get() == 1: self.remove_blocks_check.set(0) def update_index_entry(self): self.index_entry.config(state="normal") self.index_entry.delete(0,"end") self.index_entry.insert("end",str(self.board_set_index+1) + "/" + str(len(self.board_set))) self.index_entry.config(state="disabled") def update_pieces(self): if self.set_piece_marker: self.handler.board.active_blocks = self.handler.board.active_blocks * -1 self.handler.board.set_blocks[self.handler.board.active_blocks != 0] = self.handler.board.active_blocks[self.handler.board.active_blocks != 0] self.handler.board.active_blocks[...] = 0 self.set_piece_marker = False # 1 - J piece # 2 - L piece # 3 - S piece # 4 - Z piece # 5 - T piece # 6 - line piece # 7 - square piece acceptable_entries=(1,2,3,4,5,6,7) hold = self.hold_entry.get() q1 = self.queue1_entry.get() q2 = self.queue2_entry.get() q3 = self.queue3_entry.get() q4 = self.queue4_entry.get() active_piece = self.active_piece_entry.get() entry_list = [active_piece,hold,q1,q2,q3,q4] the_string = '' for i in range(len(entry_list)): if entry_list[i] not in acceptable_entries: if entry_list[i] == 'l' or entry_list[i] == 'L' or entry_list[i] == '1': the_string += '1' entry_list[i] = 1 elif entry_list[i] == 'j' or entry_list[i] == 'J' or entry_list[i] == '2': the_string += '2' entry_list[i] = 2 elif entry_list[i] == 's' or entry_list[i] == 'S' or entry_list[i] == '3': the_string += '3' entry_list[i] = 3 elif entry_list[i] == 'z' or entry_list[i] == 'Z' or entry_list[i] == '4': the_string += '4' entry_list[i] = 4 elif entry_list[i] == 't' or entry_list[i] == 'T' or entry_list[i] == '5': the_string += '5' entry_list[i] = 5 elif entry_list[i] == 'line' or entry_list[i] == 'LINE' or entry_list[i] == '6': the_string += '6' entry_list[i] = 6 elif entry_list[i] == 'square' or entry_list[i] == 'SQUARE' or entry_list[i] == '7': the_string += '7' entry_list[i] = 7 else: the_string += '0' entry_list[i] = 0 self.handler.board.held_piece = int(the_string[1]) self.display.hold_box_update(piece = entry_list[1]) self.handler.board.piece_queue = entry_list[2:] while 0 in self.handler.board.piece_queue: self.handler.board.piece_queue.pop(self.handler.board.piece_queue.index(0)) self.display.queue_images_update(new_queue=the_string[2:]) active_piece = entry_list[0] if active_piece in acceptable_entries: self.handler.board.active_blocks[...] = 0 self.handler.board.piece_queue = [active_piece] + self.handler.board.piece_queue next_piece = self.handler.board.piece_queue.pop(0) self.handler.board.set_blocks if self.handler.board.auto_get_next_piece: if not self.handler.board.get_next_piece(next_piece): self.handler.board.game_lost = True self.update_display() print("Board updated\n") def resize_CLI_window(self): def get_windows(): def check(hwnd, param): title = win32gui.GetWindowText(hwnd) # print("title: " + str(title)) if 'python -u' in title: param.append(hwnd) winds = [] win32gui.EnumWindows(check, winds) return winds for window in get_windows(): win32gui.MoveWindow(window,0,0,868,1020,True) def build_it(self): if not self.on_builder: self.handler = Build(self.handler.board) self.on_builder = True self.state_change("disabled") self.board_set = self.handler.go_through_queue() # favorite = self.handler.get_favorite(self.board_set) self.board_set_index = 0 self.handler.board = self.board_set[0] self.update_index_entry() self.update_display() self.set_piece_marker = True self.state_change("normal") self.master.deiconify() self.master.focus_force() def break_it(self): if self.on_builder: self.handler = Break(self,self.handler.board) self.on_builder = False self.state_change("disabled") self.board_set = self.handler.go_through_queue() self.board_set_index = 0 self.handler.board = self.board_set[0] self.update_index_entry() self.update_display() self.set_piece_marker = True self.state_change("normal") self.master.deiconify() self.master.focus_force()
class ResizeImageDialog(CustomDialog): def __init__(self, root, width, height, maintain_aspect_ratio=False, primary_dimension='width', title="Resize", on_change=list(), on_cancel=list(), on_confirm=list(), **kwargs): self.init_width = width self.init_height = height self.init_maintain_aspect_ratio = maintain_aspect_ratio self.init_primary_dimension = primary_dimension self.on_change = on_change self.on_confirm = on_confirm self.on_cancel = on_cancel self.window = Toplevel() self.window.title(title) self.window.transient(root) self.window.grab_set() self.primary_dimension = StringVar() self.primary_dimension.set(primary_dimension) self.resize_mode = StringVar() self.resize_mode.set('percentage') self.resize_percentage = IntVar() self.resize_percentage.set(100.0) self.resize_width = IntVar() self.resize_width.set(width) self.resize_height = IntVar() self.resize_height.set(height) self.maintain_aspect_ratio = IntVar() # See https://stackoverflow.com/a/4140988/11628429 self.vcmd_is_float = (self.window.register(self.is_float), '%P') self.vcmd_is_int = (self.window.register(self.is_int), '%P') self.percentage_radiobutton = Radiobutton(self.window, text='By percentage', value='percentage', variable=self.resize_mode, command=self.set_mode) self.percentage_radiobutton.grid(row=0, column=0) self.percentage_entry = Spinbox(self.window, from_=0, to=float('inf'), textvariable=self.resize_percentage, validate='all', validatecommand=self.vcmd_is_float) self.percentage_entry.grid(row=0, column=1) self.absolute_radiobutton = Radiobutton(self.window, text='By absolute value', value='absolute', variable=self.resize_mode, command=self.set_mode) self.absolute_radiobutton.grid(row=2, column=0) self.ratio_checkbox = Checkbutton(self.window, text='Maintain aspect ratio', variable=self.maintain_aspect_ratio, command=self.ratio_change) self.ratio_checkbox.grid(row=3, column=0) self.width_label = Label(self.window, text='Width') self.width_label.grid(row=5, column=0) self.width_entry = Spinbox( self.window, from_=0, to=float('inf'), textvariable=self.resize_width, validate='all', validatecommand=self.vcmd_is_int ) # needs a command to respect aspect ratio on change self.width_entry.grid(row=5, column=1) self.height_label = Label(self.window, text='Height') self.height_label.grid(row=6, column=0) self.height_entry = Spinbox(self.window, from_=0, to=float('inf'), textvariable=self.resize_height, validate='all', validatecommand=self.vcmd_is_int) self.height_entry.grid(row=6, column=1) self.cancel_button = Button(self.window, text='Cancel', command=self.cancel) self.cancel_button.grid(row=9, column=0) self.reset_button = Button(self.window, text='Reset', command=self.reset) self.reset_button.grid(row=9, column=1) self.confirm_button = Button(self.window, text='Confirm', command=self.confirm) self.confirm_button.grid(row=9, column=2) self.resize_percentage.trace('w', self.on_percentage_change) self.resize_width_trace_id = self.resize_width.trace( 'w', self.on_width_change) self.resize_height_trace_id = self.resize_height.trace( 'w', self.on_height_change) self.set_mode() def set_resize_width_without_trace(self, value): if not isinstance(value, int): raise TypeError('height should be an int') self.resize_width.trace_vdelete("w", self.resize_width_trace_id) self.resize_width.set(value) self.resize_width_trace_id = self.resize_width.trace( 'w', self.on_width_change) def set_resize_height_without_trace(self, value): if not isinstance(value, int): raise TypeError('width should be an int') self.resize_height.trace_vdelete("w", self.resize_height_trace_id) self.resize_height.set(value) self.resize_height_trace_id = self.resize_height.trace( 'w', self.on_height_change) def on_update(self, *args): mode = self.resize_mode.get() for callback in self.on_change: if mode == 'percentage': percentage = self.resize_percentage.get() / 100 callback(percentage, percentage, self.maintain_aspect_ratio.get(), self.primary_dimension.get()) else: callback(self.resize_width.get(), self.resize_height.get(), self.maintain_aspect_ratio.get(), self.primary_dimension.get()) def on_percentage_change(self, *args): self.on_update() def on_width_change(self, *args): self.primary_dimension.set('width') if self.maintain_aspect_ratio.get(): self.set_resize_height_without_trace( round(self.init_height * (self.resize_width.get() / self.init_width))) self.on_update() def on_height_change(self, *args): self.primary_dimension.set('height') if self.maintain_aspect_ratio.get(): self.set_resize_width_without_trace( round(self.init_width * (self.resize_height.get() / self.init_height))) self.on_update() def reset(self): self.resize_percentage.set(100.0) self.set_resize_width_without_trace(self.init_width) self.set_resize_height_without_trace(self.init_height) self.maintain_aspect_ratio.set(self.init_maintain_aspect_ratio) self.primary_dimension.set(self.init_primary_dimension) self.on_update() def set_mode(self): mode = self.resize_mode.get() if mode == 'percentage': self.percentage_entry.config(state='normal') self.ratio_checkbox.config(state='disabled') self.width_label.config(state='disabled') self.width_entry.config(state='disabled') self.height_label.config(state='disabled') self.height_entry.config(state='disabled') else: self.percentage_entry.config(state='disabled') self.ratio_checkbox.config(state='normal') self.width_label.config(state='normal') self.width_entry.config(state='normal') self.height_label.config(state='normal') self.height_entry.config(state='normal') def is_float(self, P): try: float(P) return True except ValueError: return False def is_int(self, P): return str.isdecimal(P) def ratio_change(self): if self.maintain_aspect_ratio.get(): if self.primary_dimension.get() == 'width': self.set_resize_height_without_trace( round(self.init_height * (self.resize_width.get() / self.init_width))) else: self.set_resize_width_without_trace( round(self.init_width * (self.resize_height.get() / self.init_height))) self.on_update() print(self.maintain_aspect_ratio.get()) print('w', self.resize_width.get()) print('h', self.resize_height.get())
class PyRegexEvaluator(Frame): def centre_window(self): """ Display's your gui in the centre of the screen """ w = 685 # Sets your gui's width h = 635 # Sets your gui's height sw = self.root.winfo_screenwidth() sh = self.root.winfo_screenheight() x = (sw - w) // 2 # Use integer devision to avoid having to convert y = (sh - h) // 2 # float to int self.root.geometry('{:d}x{:d}+{:d}+{:d}'.format(w, h, x, y)) def __init__(self, parent, *args, **kwargs): Frame.__init__(self, parent, *args, **kwargs) self.root = parent self.centre_window() centre_title_text = (' ' * 40) # Uses spaces to center Title title_text = 'Python Regular Expression Checker - By Jack Ackermann' self.root.title(centre_title_text + title_text) self.root.iconbitmap('images\icon.ico') self.grid(column=0, row=0, sticky='nsew', padx=12, pady=5) self.create_widgets() self.create_right_click_menu() def create_widgets(self): '''Create and load all widgets''' # Entry widget and Label Section label_text = 'Please enter regex expression to find: ' self.regex_label = tk.Label(self, text=label_text) self.regex_label.grid(row=0, column=0, sticky="w", pady=15) self.regex_pattern = tk.StringVar() self.regex_string = Entry(self, textvariable=self.regex_pattern) self.regex_string.config(borderwidth=2, relief='sunken', width=70) self.regex_string.grid(row=0, column=0, sticky="e", pady=15) # Data widget and Label Section. Data to be searched. label_data1 = 'Enter data below that you want to search. ' label_data2 = 'Results are then highlighted using re.finditer' self.data_label = tk.Label(self, text=label_data1 + label_data2) self.data_label.grid(row=1, column=0, sticky="w") self.data_textbox = Text(self, borderwidth=2, relief='sunken') self.data_textbox.config(height=15, width=80) self.data_textbox.grid(row=2, column=0, sticky="new") self.scrollbar = Scrollbar(self, command=self.data_textbox.yview) self.scrollbar.grid(row=2, column=1, sticky='ns') self.data_textbox['yscrollcommand'] = self.scrollbar.set # Display regex results and Label section label_output = 'All the matches below were found using re.findall' self.label_output = tk.Label(self, text=label_output) self.label_output.grid(row=3, column=0, sticky="w") self.output_textbox = Text(self, borderwidth=2, relief='sunken') self.output_textbox.config(height=15, width=80) self.output_textbox.grid(row=4, column=0, sticky="new") self.scrollbar2 = Scrollbar(self, command=self.output_textbox.yview) self.scrollbar2.grid(row=4, column=1, sticky='ns') self.output_textbox['yscrollcommand'] = self.scrollbar2.set # Create Two Button Widgets self.find_btn = ttk.Button(self, text='Find', command=self.on_find) self.find_btn.grid(row=5, sticky='E') self.exit_btn = ttk.Button(self, text='Exit', command=self.on_exit) self.exit_btn.grid(row=5, column=0, sticky='W', pady=15) # Create a Checkbutton Widget self.auto_var = tk.IntVar() self.auto_find = Checkbutton(self, variable=self.auto_var, command=self.on_auto, background='pink') self.auto_find.config(text='Turns on Auto Search as you type') self.auto_find.grid(row=5, column=0, sticky='') self.auto_find.deselect() def create_right_click_menu(self): '''Creates and binds the right click popup menu''' # Instanciate the imported popup class self.popup = RightClickMenu(self.master, self.regex_pattern) self.popup2 = RightClickMenu(self.master, self.data_textbox) self.popup3 = RightClickMenu(self.master, self.output_textbox) # Bind the popup menus and Enter Key to the appropriate widgets. self.regex_string.bind("<Button-3>", self.popup.entry_popup) self.data_textbox.bind("<Button-3>", self.popup2.text_popup) self.output_textbox.bind("<Button-3>", self.popup3.text_popup) self.regex_string.bind("<Return>", lambda _: self.on_find()) # Method for the find_btn, <Return> bind and Checkbutton def on_find(self, a=None, b=None, c=None): """ Takes three arguments with default values: a, b, c These arguments are needed for the trace method of StringVar() Instanciate and use the Highlighter class """ self.highlighter = Highlighter(self.regex_pattern, self.data_textbox, self.output_textbox) self.highlighter.find_matches() # Method for the self.auto_find checkbutton def on_auto(self): """ If the self.auto_find Checkbox is selected, the find button is disabled and the <Return> key is unbound The self.regex_pattern.trace is created that calls the on_find method everytime the variable changes. If the self.auto_find Checkbox is unselected, the find button gets re-enabled and the <Return> key bind is set. And the self.regex_pattern.trace is deleted """ trace_id = '' if self.auto_var.get() == 1: self.find_btn.config(state='disabled') self.regex_string.unbind("<Return>") self.regex_pattern.trace_id = self.regex_pattern.trace("w", self.on_find) else: self.find_btn.config(state='enabled') self.regex_string.bind("<Return>", lambda _: self.on_find()) self.regex_pattern.trace_vdelete("w", self.regex_pattern.trace_id) # Exits the program. Linked to the Exit Button def on_exit(self): self.root.destroy()