Beispiel #1
0
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()
Beispiel #2
0
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()
Beispiel #3
0
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")
Beispiel #4
0
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)
Beispiel #5
0
    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)
Beispiel #6
0
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)
Beispiel #9
0
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()
Beispiel #11
0
                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)
Beispiel #12
0
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
Beispiel #13
0
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.")
Beispiel #14
0
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()
Beispiel #15
0
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]
Beispiel #18
0
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)
Beispiel #20
0
    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)
Beispiel #21
0
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")
Beispiel #23
0
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
Beispiel #24
0
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)
Beispiel #25
0
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())
Beispiel #26
0
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())
Beispiel #27
0
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()
Beispiel #28
0
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)
Beispiel #29
0
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()
Beispiel #30
0
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())
Beispiel #31
0
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()