Skip to main content
update formatting, capitalize proper nouns
Source Link

This post is less of a question and more of a hope for people to see my code which iI know is far from great and give me some direction or simple tips on improving the quality of it.

Normal Stud:

Normal Stud  

Active Stud:

Active Stud

The program is a small simple class which inherits tkinterstkinter's Canvas object and uses it to create a 'for purpose' Touchscreen Pattern Password. It uses Images which have been attached and need to be placed in the same folder as the code which are for the pattern studs and then uses a series of bind events to know where the touch presses happen.

Have a play around if you wish and let me know any structure / coding improvement iI could make. FYI this program was coded with python3.6 on windows operating system :)

Thankyou, Jack ######CODE BELOW######

Code:

This post is less of a question and more of a hope for people to see my code which i know is far from great and give me some direction or simple tips on improving the quality of it.

Normal Stud  Active Stud

The program is a small simple class which inherits tkinters Canvas object and uses it to create a 'for purpose' Touchscreen Pattern Password. It uses Images which have been attached and need to be placed in the same folder as the code which are for the pattern studs and then uses a series of bind events to know where the touch presses happen.

Have a play around if you wish and let me know any structure / coding improvement i could make. FYI this program was coded with python3.6 on windows operating system :)

Thankyou, Jack ######CODE BELOW######

This post is less of a question and more of a hope for people to see my code which I know is far from great and give me some direction or simple tips on improving the quality of it.

Normal Stud:

Normal Stud

Active Stud:

Active Stud

The program is a small simple class which inherits tkinter's Canvas object and uses it to create a 'for purpose' Touchscreen Pattern Password. It uses Images which have been attached and need to be placed in the same folder as the code which are for the pattern studs and then uses a series of bind events to know where the touch presses happen.

Have a play around if you wish and let me know any structure / coding improvement I could make. FYI this program was coded with python3.6 on windows operating system :)

Code:

Tweeted twitter.com/StackCodeReview/status/1540349034547875844
Rollback to Revision 2
Source Link
pacmaninbw
  • 26.2k
  • 13
  • 47
  • 114
import tkinter as tk

class PatternPassword(tk.Canvas):
    '''
    Pattern Password Class which creates a 3x3 grid of studs where
    the user is able to input a code relative to a pattern
    corresponding to a code

    Three arguments are available:
      [+] show_pattern
        # Will Show the user what order they are selecting the studs
        [-] True
        [-] False 
      [+] show_numbers
        # Will Show numbers corresponding to each studs code value
        [-] True
        [-] False
      [+] max_length
        # Will determine the length of the pattern the user is allowed to make
        [-] 1-9 (Integer)
    '''
    def __init__(self, show_pattern=False, show_numbers=False, max_length=9):

        super().__init__()

        #CONSTANTS
        LOWEST_LENGTH = 1
        HIGHEST_LENGTH = 9

        CANVAS_WIDTH = 300
        CANVAS_HEIGHT = 300

        self.STUD_START_X, self.STUD_START_Y = 20, 20
        self.STUD_ADD_X, self.STUD_ADD_Y = 100, 100
        self.STUD_NEXTROWVAL_X = 320
       if self.X,1 self.Y< =max_length self.STUD_START_X,> self.STUD_START_Y9:
        self.TEXT_DISPLACEMENT = 34

      #print('[*] Not ifaloud LOWEST_LENGTHmore <than max_length9 >as HIGHEST_LENGTH:max_length')
            raise Exception('[*] Max length must be between 1 and 9')

        #root canvas configuration and bindings
        self.config(bg='grey', width=CANVAS_WIDTHwidth=300, height=CANVAS_HEIGHTheight=300)
        self.bind_all("<B1-Motion>", self.ShowInfo)
        self.bind_all("<ButtonPress-1>", self.ShowInfo)

        #make arguments available to all class methods
        self.show_pattern = show_pattern
        self.show_numbers = show_numbers
        self.max_length = max_length

        #class pattern variable
        self.pattern = tk.StringVar()
        self.pattern.set('Pattern Password: ')

        #cache variables
        self.current_widget = None
        self.line = None
        self.x1, self.y1, self.x2, self.y2 = None, None, None, None

        self.activeStub = tk.PhotoImage(file='stubActive.png')
        self.stubclick_num = tk.PhotoImage(file='stub.png')
0
        self.hasClickedx1, self.y1, self.x2, self.y2 = FalseNone, None, None, None
        self.lines = []
        self.points = []
        self.stubs = {}

        #Setup the widgets in the canvas
        self.SetupStubs()

    def DeleteLine(self):

        #Deletes the current line on the canvas
        self.delete(self.line)

    def AddLine(self):

        #Creates a new line on the canvas and assigns to class variable
        self.line = self.create_line(self.points, fill="white", arrow=tk.LAST, width=3)

    def DrawLine(self, middleBounds):

        #Creates a new line point and then will try to call the AddLine method

        self.x = middleBounds[0]
       def AddLine(self.y =, middleBounds[1]event):

        self.points.appenddelete(self.xlines[0])
        del self.pointslines[0]
        line = self.appendcreate_line(self.ypoints, fill="white", arrow=tk.LAST, width=3)
        self.lines.append(line)

    def DrawLine(self, event, middleBounds):
       
        if self.hasClickedclick_num==0:
           self.x1=middleBounds[0]
           self.AddLiney1=middleBounds[1]
           self.click_num=1
           self.points.append(self.x1)
           self.points.append(self.y1)
        else:
           self.x2=middleBounds[0]
           self.hasClickedy2=middleBounds[1]
           self.points.append(self.x2)
           self.points.append(self.y2)
           if len(self.lines) == 1:
               self.AddLine(event)
               return
           
           line = Trueself.create_line(self.x1,self.y1,self.x2,self.y2, fill="white", width=3, arrow=tk.LAST, smooth=1, splinesteps=12)
           self.lines.append(line)

    def AddToPattern(self, number):

        #Adds stud code number to the total password
        self.pattern.set(f'Pattern Password: {self.pattern.get()[18:]}{str(number)}')

    def ActivateStub(self, number):

        #Makes stud turn green when pressed
        self.itemconfig(self.stubs[number-1], image=self.activeStub)

    def ShowInfo(self, event):

        '''
        Will be called everytime the mouse button 1 is pressed down
        and moved. This method will constantly get the coordinates of
        the mouse and compare them with the bounds of each stud.
        If the mouse is inside one of the studs bounds and is not
        the 'self.current_widget' selected then it will be made
        the current widget and methods will be called on it
        to highlight it has been selected and to draw the lines etc.
        '''

        for stubNumber in list(self.stubs.values()):

            bound = self.bbox(stubNumber)
            x = [bound[0], bound[2]]
            y = [bound[1], bound[3]]
            middleBoundX = sum(x) / len(x)
            middleBoundY = sum(y) / len(y)
            middleBounds = [middleBoundX, middleBoundY]
            
            if bound[0] < event.x < bound[2] and bound[1] < event.y < bound[3]:

                widget = stubNumber 

                x = [bound[0], bound[2]]
                y = [bound[1], bound[3]]
                middleBoundX = sum(x) / len(x)
                middleBoundYwidget = sum(y) / len(y)
              stubNumber  middleBounds = [middleBoundX, middleBoundY] 

                if self.current_widget != widget:
                    self.current_widget = widget
                    if len(self.pattern.get()) < (18+self.max_length) and str(self.current_widget) not in self.pattern.get()[18:]:
                        self.AddToPattern(self.current_widget)
                        self.ActivateStub(self.current_widget)
                        if self.show_pattern:
                            self.DeleteLine()
                            self.DrawLine(event, middleBounds)
                    
    def SetupStubs(self, text=False):

        self.X,x=20
        y=20

        self.Ystub = selftk.STUD_START_X,PhotoImage(file='stub.png')
        self.STUD_START_Ystubs = {}

        for stubNum in range(9):

            if text:
                textID = self.create_text(self.X+self.TEXT_DISPLACEMENT, self.Y+self.TEXT_DISPLACEMENT, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
            else:
                stubButtonID = self.create_image(self.Xx,self.Yy,anchor=tk.NW,image=self.stub)
                self.stubs.update({stubNum: stubButtonID})
            
            self.X += self.STUD_ADD_X
            if self.X == self.STUD_NEXTROWVAL_X:
                self.Y += self.STUD_ADD_Y
                self.X = self.STUD_START_X

            x += 100

            if notx text== 320:
                y += 100
                x = 20

            self.stubs.update({stubNum: stubButtonID})
         
        if self.show_numbers:
            x=20
            y=20
            for stubNum in range(9):
                self.SetupStubscreate_text(Truex+34, y+34, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
                x += 100

                if x == 320:
                    y += 100
                    x = 20

    def ClearPattern(self):

        self.pattern.set('Pattern Password: ')
        for stub in list(self.stubs.values()):
            #stub.config(image=self.stub)
            self.itemconfig(stub, image=self.stub)

         for line in self.pattern.set('Pattern Passwordlines: ')
            self.delete(self.line)
        self.hasClickedclick_num = False0
        self.points = []


if __name__ == '__main__':

    main = tk.Tk()
    main.geometry('500x500')
    main.config(bg='grey')

    title = tk.Label(main, text='Pattern Password', bg=main['bg'], fg='white', font=('Verdana Pro Light', 32, 'underline'))
    title.pack(fill=tk.X, pady=20)

    pattern = PatternPassword(show_pattern=True, show_numbers=Trueshow_numbers=False, max_length=9)
    pattern.pack()

    controlFrame = tk.Frame(main, bg='grey')
    controlFrame.pack_propagate(False)
    controlFrame.pack(padx=(50,0), pady=20, ipady=40, fill=tk.X, expand=1)

    passLabel = tk.Label(controlFrame, textvariable=pattern.pattern, font=('Verdana Pro Light', 18), bg='grey', fg='white')
    passLabel.pack(side=tk.LEFT)

    clearPattern = tk.Button(controlFrame, text='Clear', font=('Arial', 20), bg='grey', activebackground='grey', fg='white', activeforeground='white', bd=0, highlightthickness=0, command=pattern.ClearPattern)
    clearPattern.pack(side=tk.LEFT, padx=(20,0), ipadx=20, ipady=3)

    main.mainloop()


import tkinter as tk

class PatternPassword(tk.Canvas):
    '''
    Pattern Password Class which creates a 3x3 grid of studs where
    the user is able to input a code relative to a pattern
    corresponding to a code

    Three arguments are available:
      [+] show_pattern
        # Will Show the user what order they are selecting the studs
        [-] True
        [-] False 
      [+] show_numbers
        # Will Show numbers corresponding to each studs code value
        [-] True
        [-] False
      [+] max_length
        # Will determine the length of the pattern the user is allowed to make
        [-] 1-9 (Integer)
    '''
    def __init__(self, show_pattern=False, show_numbers=False, max_length=9):

        super().__init__()

        #CONSTANTS
        LOWEST_LENGTH = 1
        HIGHEST_LENGTH = 9

        CANVAS_WIDTH = 300
        CANVAS_HEIGHT = 300

        self.STUD_START_X, self.STUD_START_Y = 20, 20
        self.STUD_ADD_X, self.STUD_ADD_Y = 100, 100
        self.STUD_NEXTROWVAL_X = 320
        self.X, self.Y = self.STUD_START_X, self.STUD_START_Y
        self.TEXT_DISPLACEMENT = 34

        if LOWEST_LENGTH < max_length > HIGHEST_LENGTH:
            raise Exception('[*] Max length must be between 1 and 9')

        #root canvas configuration and bindings
        self.config(bg='grey', width=CANVAS_WIDTH, height=CANVAS_HEIGHT)
        self.bind_all("<B1-Motion>", self.ShowInfo)
        self.bind_all("<ButtonPress-1>", self.ShowInfo)

        #make arguments available to all class methods
        self.show_pattern = show_pattern
        self.show_numbers = show_numbers
        self.max_length = max_length

        #class pattern variable
        self.pattern = tk.StringVar()
        self.pattern.set('Pattern Password: ')

        #cache variables
        self.current_widget = None
        self.line = None
        self.x1, self.y1, self.x2, self.y2 = None, None, None, None

        self.activeStub = tk.PhotoImage(file='stubActive.png')
        self.stub = tk.PhotoImage(file='stub.png')

        self.hasClicked = False
        
        self.points = []
        self.stubs = {}

        #Setup the widgets in the canvas
        self.SetupStubs()

    def DeleteLine(self):

        #Deletes the current line on the canvas
        self.delete(self.line)

    def AddLine(self):

        #Creates a new line on the canvas and assigns to class variable
        self.line = self.create_line(self.points, fill="white", arrow=tk.LAST, width=3)

    def DrawLine(self, middleBounds):

        #Creates a new line point and then will try to call the AddLine method

        self.x = middleBounds[0]
        self.y = middleBounds[1]

        self.points.append(self.x)
        self.points.append(self.y)

        if self.hasClicked:
            self.AddLine()
        else:
            self.hasClicked = True

    def AddToPattern(self, number):

        #Adds stud code number to the total password
        self.pattern.set(f'Pattern Password: {self.pattern.get()[18:]}{str(number)}')

    def ActivateStub(self, number):

        #Makes stud turn green when pressed
        self.itemconfig(self.stubs[number-1], image=self.activeStub)

    def ShowInfo(self, event):

        '''
        Will be called everytime the mouse button 1 is pressed down
        and moved. This method will constantly get the coordinates of
        the mouse and compare them with the bounds of each stud.
        If the mouse is inside one of the studs bounds and is not
        the 'self.current_widget' selected then it will be made
        the current widget and methods will be called on it
        to highlight it has been selected and to draw the lines etc.
        '''

        for stubNumber in list(self.stubs.values()):

            bound = self.bbox(stubNumber)
            
            if bound[0] < event.x < bound[2] and bound[1] < event.y < bound[3]:

                widget = stubNumber 

                x = [bound[0], bound[2]]
                y = [bound[1], bound[3]]
                middleBoundX = sum(x) / len(x)
                middleBoundY = sum(y) / len(y)
                middleBounds = [middleBoundX, middleBoundY] 

                if self.current_widget != widget:
                    self.current_widget = widget
                    if len(self.pattern.get()) < (18+self.max_length) and str(self.current_widget) not in self.pattern.get()[18:]:
                        self.AddToPattern(self.current_widget)
                        self.ActivateStub(self.current_widget)
                        if self.show_pattern:
                            self.DeleteLine()
                            self.DrawLine(middleBounds)
                    
    def SetupStubs(self, text=False):

        self.X, self.Y = self.STUD_START_X, self.STUD_START_Y

        for stubNum in range(9):

            if text:
                textID = self.create_text(self.X+self.TEXT_DISPLACEMENT, self.Y+self.TEXT_DISPLACEMENT, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
            else:
                stubButtonID = self.create_image(self.X,self.Y,anchor=tk.NW,image=self.stub)
                self.stubs.update({stubNum: stubButtonID})
            
            self.X += self.STUD_ADD_X
            if self.X == self.STUD_NEXTROWVAL_X:
                self.Y += self.STUD_ADD_Y
                self.X = self.STUD_START_X

        if not text:
            if self.show_numbers:
                self.SetupStubs(True)

    def ClearPattern(self):

        for stub in list(self.stubs.values()):
            self.itemconfig(stub, image=self.stub)

         self.pattern.set('Pattern Password: ')
        self.delete(self.line)
        self.hasClicked = False
        self.points = []


if __name__ == '__main__':

    main = tk.Tk()
    main.geometry('500x500')
    main.config(bg='grey')

    title = tk.Label(main, text='Pattern Password', bg=main['bg'], fg='white', font=('Verdana Pro Light', 32, 'underline'))
    title.pack(fill=tk.X, pady=20)

    pattern = PatternPassword(show_pattern=True, show_numbers=True, max_length=9)
    pattern.pack()

    controlFrame = tk.Frame(main, bg='grey')
    controlFrame.pack_propagate(False)
    controlFrame.pack(padx=(50,0), pady=20, ipady=40, fill=tk.X, expand=1)

    passLabel = tk.Label(controlFrame, textvariable=pattern.pattern, font=('Verdana Pro Light', 18), bg='grey', fg='white')
    passLabel.pack(side=tk.LEFT)

    clearPattern = tk.Button(controlFrame, text='Clear', font=('Arial', 20), bg='grey', activebackground='grey', fg='white', activeforeground='white', bd=0, highlightthickness=0, command=pattern.ClearPattern)
    clearPattern.pack(side=tk.LEFT, padx=(20,0), ipadx=20, ipady=3)

    main.mainloop()


import tkinter as tk

class PatternPassword(tk.Canvas):

    def __init__(self, show_pattern=False, show_numbers=False, max_length=9):

        super().__init__()

        if 1 < max_length > 9:
            #print('[*] Not aloud more than 9 as max_length')
            raise Exception('[*] Max length must be between 1 and 9')

        self.config(bg='grey', width=300, height=300)
        self.bind_all("<B1-Motion>", self.ShowInfo)
        self.bind_all("<ButtonPress-1>", self.ShowInfo)


        self.show_pattern = show_pattern
        self.show_numbers = show_numbers
        self.max_length = max_length

        self.pattern = tk.StringVar()
        self.pattern.set('Pattern Password: ')
        self.current_widget = None
        self.activeStub = tk.PhotoImage(file='stubActive.png')
        self.click_num = 0
        self.x1, self.y1, self.x2, self.y2 = None, None, None, None
        self.lines = []
        self.points = []

        self.SetupStubs()

    def AddLine(self, event):

        self.delete(self.lines[0])
        del self.lines[0]
        line = self.create_line(self.points, fill="white", arrow=tk.LAST, width=3)
        self.lines.append(line)

    def DrawLine(self, event, middleBounds):
       
        if self.click_num==0:
           self.x1=middleBounds[0]
           self.y1=middleBounds[1]
           self.click_num=1
           self.points.append(self.x1)
           self.points.append(self.y1)
        else:
           self.x2=middleBounds[0]
           self.y2=middleBounds[1]
           self.points.append(self.x2)
           self.points.append(self.y2)
           if len(self.lines) == 1:
               self.AddLine(event)
               return
           
           line = self.create_line(self.x1,self.y1,self.x2,self.y2, fill="white", width=3, arrow=tk.LAST, smooth=1, splinesteps=12)
           self.lines.append(line)

    def AddToPattern(self, number):

        self.pattern.set(f'Pattern Password: {self.pattern.get()[18:]}{str(number)}')

    def ActivateStub(self, number):

        self.itemconfig(self.stubs[number-1], image=self.activeStub)

    def ShowInfo(self, event):

        for stubNumber in list(self.stubs.values()):

            bound = self.bbox(stubNumber)
            x = [bound[0], bound[2]]
            y = [bound[1], bound[3]]
            middleBoundX = sum(x) / len(x)
            middleBoundY = sum(y) / len(y)
            middleBounds = [middleBoundX, middleBoundY]
            
            if bound[0] < event.x < bound[2] and bound[1] < event.y < bound[3]:

                widget = stubNumber     

                if self.current_widget != widget:
                    self.current_widget = widget
                    if len(self.pattern.get()) < (18+self.max_length) and str(self.current_widget) not in self.pattern.get()[18:]:
                        self.AddToPattern(self.current_widget)
                        self.ActivateStub(self.current_widget)
                        if self.show_pattern:
                            self.DrawLine(event, middleBounds)
                    
    def SetupStubs(self):

        x=20
        y=20

        self.stub = tk.PhotoImage(file='stub.png')
        self.stubs = {}

        for stubNum in range(9):

            stubButtonID = self.create_image(x,y,anchor=tk.NW,image=self.stub)

            x += 100

            if x == 320:
                y += 100
                x = 20

            self.stubs.update({stubNum: stubButtonID})
         
        if self.show_numbers:
            x=20
            y=20
            for stubNum in range(9):
                self.create_text(x+34, y+34, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
                x += 100

                if x == 320:
                    y += 100
                    x = 20

    def ClearPattern(self):

        self.pattern.set('Pattern Password: ')
        for stub in list(self.stubs.values()):
            #stub.config(image=self.stub)
            self.itemconfig(stub, image=self.stub)
        for line in self.lines:
            self.delete(line)
        self.click_num = 0
        self.points = []


if __name__ == '__main__':

    main = tk.Tk()
    main.geometry('500x500')
    main.config(bg='grey')

    title = tk.Label(main, text='Pattern Password', bg=main['bg'], fg='white', font=('Verdana Pro Light', 32, 'underline'))
    title.pack(fill=tk.X, pady=20)

    pattern = PatternPassword(show_pattern=True, show_numbers=False, max_length=9)
    pattern.pack()

    controlFrame = tk.Frame(main, bg='grey')
    controlFrame.pack_propagate(False)
    controlFrame.pack(padx=(50,0), pady=20, ipady=40, fill=tk.X, expand=1)

    passLabel = tk.Label(controlFrame, textvariable=pattern.pattern, font=('Verdana Pro Light', 18), bg='grey', fg='white')
    passLabel.pack(side=tk.LEFT)

    clearPattern = tk.Button(controlFrame, text='Clear', font=('Arial', 20), bg='grey', activebackground='grey', fg='white', activeforeground='white', bd=0, highlightthickness=0, command=pattern.ClearPattern)
    clearPattern.pack(side=tk.LEFT, padx=(20,0), ipadx=20, ipady=3)

    main.mainloop()


Update: Revised Code as suggested
Source Link
Jack
  • 41
  • 5
import tkinter as tk

class PatternPassword(tk.Canvas):
    '''
    Pattern Password Class which creates a 3x3 grid of studs where
    the user is able to input a code relative to a pattern
    corresponding to a code

    Three arguments are available:
      [+] show_pattern
        # Will Show the user what order they are selecting the studs
        [-] True
        [-] False 
      [+] show_numbers
        # Will Show numbers corresponding to each studs code value
        [-] True
        [-] False
      [+] max_length
        # Will determine the length of the pattern the user is allowed to make
        [-] 1-9 (Integer)
    '''
    def __init__(self, show_pattern=False, show_numbers=False, max_length=9):

        super().__init__()

        if#CONSTANTS
        LOWEST_LENGTH = 1 
 < max_length >     HIGHEST_LENGTH = 9: 

        CANVAS_WIDTH = 300
  #print('[*] Not aloud more than 9 asCANVAS_HEIGHT max_length')= 300

        self.STUD_START_X, self.STUD_START_Y = 20, 20
        self.STUD_ADD_X, self.STUD_ADD_Y = 100, 100
        self.STUD_NEXTROWVAL_X = 320
        self.X, self.Y = self.STUD_START_X, self.STUD_START_Y
        self.TEXT_DISPLACEMENT = 34

        if LOWEST_LENGTH < max_length > HIGHEST_LENGTH:
            raise Exception('[*] Max length must be between 1 and 9')

        #root canvas configuration and bindings
        self.config(bg='grey', width=300width=CANVAS_WIDTH, height=300height=CANVAS_HEIGHT)
        self.bind_all("<B1-Motion>", self.ShowInfo)
        self.bind_all("<ButtonPress-1>", self.ShowInfo)

 
        #make arguments available to all class methods
        self.show_pattern = show_pattern
        self.show_numbers = show_numbers
        self.max_length = max_length

        #class pattern variable
        self.pattern = tk.StringVar()
        self.pattern.set('Pattern Password: ')

        #cache variables
        self.current_widget = None
        self.activeStub = tk.PhotoImage(file='stubActive.png')
        self.click_numline = 0None
        self.x1, self.y1, self.x2, self.y2 = None, None, None, None
 
        self.linesactiveStub = []tk.PhotoImage(file='stubActive.png')
        self.stub = tk.PhotoImage(file='stub.png')

        self.hasClicked = False
        
        self.points = []
        self.stubs = {}

        #Setup the widgets in the canvas
        self.SetupStubs()

    def AddLineDeleteLine(self, event):

        self.delete(self.lines[0])
   #Deletes the current line on delthe self.lines[0]canvas
        line = self.create_linedelete(self.points, fill="white", arrow=tk.LAST, width=3)
        self.lines.append(line)

    def DrawLineAddLine(self, event, middleBounds): 

        #Creates a new line on the canvas and assigns to class variable
        ifself.line = self.click_num==0:create_line(self.points, fill="white", arrow=tk.LAST, width=3)

    def DrawLine(self, middleBounds):

     self.x1=middleBounds[0]
   #Creates a new line point and then will try to self.y1=middleBounds[1]
call the AddLine method

        self.click_num=1x = middleBounds[0]
        self.y = middleBounds[1]

        self.points.append(self.x1x)
           self.points.append(self.y1y)

        if self.hasClicked:
            self.AddLine()
        else:
           self.x2=middleBounds[0]
           self.y2=middleBounds[1]
           self.points.append(self.x2)
           self.points.append(self.y2)
           if len(self.lines) == 1:
               self.AddLine(event)
               return
           
           linehasClicked = self.create_line(self.x1,self.y1,self.x2,self.y2, fill="white", width=3, arrow=tk.LAST, smooth=1, splinesteps=12)
           self.lines.append(line)True

    def AddToPattern(self, number):

        #Adds stud code number to the total password
        self.pattern.set(f'Pattern Password: {self.pattern.get()[18:]}{str(number)}')

    def ActivateStub(self, number):

        #Makes stud turn green when pressed
        self.itemconfig(self.stubs[number-1], image=self.activeStub)

    def ShowInfo(self, event):

        '''
        Will be called everytime the mouse button 1 is pressed down
        and moved. This method will constantly get the coordinates of
        the mouse and compare them with the bounds of each stud.
        If the mouse is inside one of the studs bounds and is not
        the 'self.current_widget' selected then it will be made
        the current widget and methods will be called on it
        to highlight it has been selected and to draw the lines etc.
        '''

        for stubNumber in list(self.stubs.values()):

            bound = self.bbox(stubNumber)
            x = [bound[0], bound[2]]
            y = [bound[1], bound[3]]
            middleBoundX = sum(x) / len(x)
            middleBoundY = sum(y) / len(y)
            middleBounds = [middleBoundX, middleBoundY]
            
            if bound[0] < event.x < bound[2] and bound[1] < event.y < bound[3]:

                widget = stubNumber 

                x = [bound[0], bound[2]]
                y = [bound[1], bound[3]]
                middleBoundX = sum(x) / len(x)
                middleBoundY = sum(y) / len(y)
                middleBounds = [middleBoundX, middleBoundY] 

                if self.current_widget != widget:
                    self.current_widget = widget
                    if len(self.pattern.get()) < (18+self.max_length) and str(self.current_widget) not in self.pattern.get()[18:]:
                        self.AddToPattern(self.current_widget)
                        self.ActivateStub(self.current_widget)
                        if self.show_pattern:
                            self.DrawLineDeleteLine(event,)
                            self.DrawLine(middleBounds)
                    
    def SetupStubs(self, text=False):

        x=20
        y=20

        self.stub =X, tk.PhotoImage(file='stubself.png')
      Y = self.stubs =STUD_START_X, {}self.STUD_START_Y

        for stubNum in range(9):

            stubButtonID = self.create_image(x,y,anchor=tk.NW,image=self.stub)

            x +=if 100
text:
            if x == 320:
 textID = self.create_text(self.X+self.TEXT_DISPLACEMENT, self.Y+self.TEXT_DISPLACEMENT, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
       y += 100   else:
                xstubButtonID = 20
self.create_image(self.X,self.Y,anchor=tk.NW,image=self.stub)
                self.stubs.update({stubNum: stubButtonID})
        
        if self.show_numbers:
            x=20
          self.X += y=20self.STUD_ADD_X
            forif stubNumself.X in== range(9)self.STUD_NEXTROWVAL_X:
                self.create_text(x+34, y+34, text=stubNum+1, fill="white", font=('HelveticaY 15+= bold'))self.STUD_ADD_Y
                xself.X +== 100self.STUD_START_X

                if x ==not 320text:
                    y +=if 100self.show_numbers:
                    x = 20self.SetupStubs(True)

    def ClearPattern(self):

        self.pattern.set('Pattern Password: ')
        for stub in list(self.stubs.values()):
            #stub.config(image=self.stub)
            self.itemconfig(stub, image=self.stub)
   
      for line in self.lines:
  pattern.set('Pattern Password: ')
        self.delete(self.line)
        self.click_numhasClicked = 0False
        self.points = []


if __name__ == '__main__':

    main = tk.Tk()
    main.geometry('500x500')
    main.config(bg='grey')

    title = tk.Label(main, text='Pattern Password', bg=main['bg'], fg='white', font=('Verdana Pro Light', 32, 'underline'))
    title.pack(fill=tk.X, pady=20)

    pattern = PatternPassword(show_pattern=True, show_numbers=Falseshow_numbers=True, max_length=9)
    pattern.pack()

    controlFrame = tk.Frame(main, bg='grey')
    controlFrame.pack_propagate(False)
    controlFrame.pack(padx=(50,0), pady=20, ipady=40, fill=tk.X, expand=1)

    passLabel = tk.Label(controlFrame, textvariable=pattern.pattern, font=('Verdana Pro Light', 18), bg='grey', fg='white')
    passLabel.pack(side=tk.LEFT)

    clearPattern = tk.Button(controlFrame, text='Clear', font=('Arial', 20), bg='grey', activebackground='grey', fg='white', activeforeground='white', bd=0, highlightthickness=0, command=pattern.ClearPattern)
    clearPattern.pack(side=tk.LEFT, padx=(20,0), ipadx=20, ipady=3)

    main.mainloop()


import tkinter as tk

class PatternPassword(tk.Canvas):

    def __init__(self, show_pattern=False, show_numbers=False, max_length=9):

        super().__init__()

        if 1 < max_length > 9:
            #print('[*] Not aloud more than 9 as max_length')
            raise Exception('[*] Max length must be between 1 and 9')

        self.config(bg='grey', width=300, height=300)
        self.bind_all("<B1-Motion>", self.ShowInfo)
        self.bind_all("<ButtonPress-1>", self.ShowInfo)

 
        self.show_pattern = show_pattern
        self.show_numbers = show_numbers
        self.max_length = max_length

        self.pattern = tk.StringVar()
        self.pattern.set('Pattern Password: ')
        self.current_widget = None
        self.activeStub = tk.PhotoImage(file='stubActive.png')
        self.click_num = 0
        self.x1, self.y1, self.x2, self.y2 = None, None, None, None
        self.lines = []
        self.points = []

        self.SetupStubs()

    def AddLine(self, event):

        self.delete(self.lines[0])
        del self.lines[0]
        line = self.create_line(self.points, fill="white", arrow=tk.LAST, width=3)
        self.lines.append(line)

    def DrawLine(self, event, middleBounds):
       
        if self.click_num==0:
           self.x1=middleBounds[0]
           self.y1=middleBounds[1]
           self.click_num=1
           self.points.append(self.x1)
           self.points.append(self.y1)
        else:
           self.x2=middleBounds[0]
           self.y2=middleBounds[1]
           self.points.append(self.x2)
           self.points.append(self.y2)
           if len(self.lines) == 1:
               self.AddLine(event)
               return
           
           line = self.create_line(self.x1,self.y1,self.x2,self.y2, fill="white", width=3, arrow=tk.LAST, smooth=1, splinesteps=12)
           self.lines.append(line)

    def AddToPattern(self, number):

        self.pattern.set(f'Pattern Password: {self.pattern.get()[18:]}{str(number)}')

    def ActivateStub(self, number):

        self.itemconfig(self.stubs[number-1], image=self.activeStub)

    def ShowInfo(self, event):

        for stubNumber in list(self.stubs.values()):

            bound = self.bbox(stubNumber)
            x = [bound[0], bound[2]]
            y = [bound[1], bound[3]]
            middleBoundX = sum(x) / len(x)
            middleBoundY = sum(y) / len(y)
            middleBounds = [middleBoundX, middleBoundY]
            
            if bound[0] < event.x < bound[2] and bound[1] < event.y < bound[3]:

                widget = stubNumber     

                if self.current_widget != widget:
                    self.current_widget = widget
                    if len(self.pattern.get()) < (18+self.max_length) and str(self.current_widget) not in self.pattern.get()[18:]:
                        self.AddToPattern(self.current_widget)
                        self.ActivateStub(self.current_widget)
                        if self.show_pattern:
                            self.DrawLine(event, middleBounds)
                    
    def SetupStubs(self):

        x=20
        y=20

        self.stub = tk.PhotoImage(file='stub.png')
        self.stubs = {}

        for stubNum in range(9):

            stubButtonID = self.create_image(x,y,anchor=tk.NW,image=self.stub)

            x += 100

            if x == 320:
                y += 100
                x = 20

            self.stubs.update({stubNum: stubButtonID})
        
        if self.show_numbers:
            x=20
            y=20
            for stubNum in range(9):
                self.create_text(x+34, y+34, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
                x += 100

                if x == 320:
                    y += 100
                    x = 20

    def ClearPattern(self):

        self.pattern.set('Pattern Password: ')
        for stub in list(self.stubs.values()):
            #stub.config(image=self.stub)
            self.itemconfig(stub, image=self.stub)
        for line in self.lines:
            self.delete(line)
        self.click_num = 0
        self.points = []


if __name__ == '__main__':

    main = tk.Tk()
    main.geometry('500x500')
    main.config(bg='grey')

    title = tk.Label(main, text='Pattern Password', bg=main['bg'], fg='white', font=('Verdana Pro Light', 32, 'underline'))
    title.pack(fill=tk.X, pady=20)

    pattern = PatternPassword(show_pattern=True, show_numbers=False, max_length=9)
    pattern.pack()

    controlFrame = tk.Frame(main, bg='grey')
    controlFrame.pack_propagate(False)
    controlFrame.pack(padx=(50,0), pady=20, ipady=40, fill=tk.X, expand=1)

    passLabel = tk.Label(controlFrame, textvariable=pattern.pattern, font=('Verdana Pro Light', 18), bg='grey', fg='white')
    passLabel.pack(side=tk.LEFT)

    clearPattern = tk.Button(controlFrame, text='Clear', font=('Arial', 20), bg='grey', activebackground='grey', fg='white', activeforeground='white', bd=0, highlightthickness=0, command=pattern.ClearPattern)
    clearPattern.pack(side=tk.LEFT, padx=(20,0), ipadx=20, ipady=3)

    main.mainloop()


import tkinter as tk

class PatternPassword(tk.Canvas):
    '''
    Pattern Password Class which creates a 3x3 grid of studs where
    the user is able to input a code relative to a pattern
    corresponding to a code

    Three arguments are available:
      [+] show_pattern
        # Will Show the user what order they are selecting the studs
        [-] True
        [-] False 
      [+] show_numbers
        # Will Show numbers corresponding to each studs code value
        [-] True
        [-] False
      [+] max_length
        # Will determine the length of the pattern the user is allowed to make
        [-] 1-9 (Integer)
    '''
    def __init__(self, show_pattern=False, show_numbers=False, max_length=9):

        super().__init__()

        #CONSTANTS
        LOWEST_LENGTH = 1 
        HIGHEST_LENGTH = 9 

        CANVAS_WIDTH = 300
        CANVAS_HEIGHT = 300

        self.STUD_START_X, self.STUD_START_Y = 20, 20
        self.STUD_ADD_X, self.STUD_ADD_Y = 100, 100
        self.STUD_NEXTROWVAL_X = 320
        self.X, self.Y = self.STUD_START_X, self.STUD_START_Y
        self.TEXT_DISPLACEMENT = 34

        if LOWEST_LENGTH < max_length > HIGHEST_LENGTH:
            raise Exception('[*] Max length must be between 1 and 9')

        #root canvas configuration and bindings
        self.config(bg='grey', width=CANVAS_WIDTH, height=CANVAS_HEIGHT)
        self.bind_all("<B1-Motion>", self.ShowInfo)
        self.bind_all("<ButtonPress-1>", self.ShowInfo)

        #make arguments available to all class methods
        self.show_pattern = show_pattern
        self.show_numbers = show_numbers
        self.max_length = max_length

        #class pattern variable
        self.pattern = tk.StringVar()
        self.pattern.set('Pattern Password: ')

        #cache variables
        self.current_widget = None
        self.line = None
        self.x1, self.y1, self.x2, self.y2 = None, None, None, None
 
        self.activeStub = tk.PhotoImage(file='stubActive.png')
        self.stub = tk.PhotoImage(file='stub.png')

        self.hasClicked = False
        
        self.points = []
        self.stubs = {}

        #Setup the widgets in the canvas
        self.SetupStubs()

    def DeleteLine(self):

        #Deletes the current line on the canvas
        self.delete(self.line)

    def AddLine(self): 

        #Creates a new line on the canvas and assigns to class variable
        self.line = self.create_line(self.points, fill="white", arrow=tk.LAST, width=3)

    def DrawLine(self, middleBounds):

        #Creates a new line point and then will try to call the AddLine method

        self.x = middleBounds[0]
        self.y = middleBounds[1]

        self.points.append(self.x)
        self.points.append(self.y)

        if self.hasClicked:
            self.AddLine()
        else:
            self.hasClicked = True

    def AddToPattern(self, number):

        #Adds stud code number to the total password
        self.pattern.set(f'Pattern Password: {self.pattern.get()[18:]}{str(number)}')

    def ActivateStub(self, number):

        #Makes stud turn green when pressed
        self.itemconfig(self.stubs[number-1], image=self.activeStub)

    def ShowInfo(self, event):

        '''
        Will be called everytime the mouse button 1 is pressed down
        and moved. This method will constantly get the coordinates of
        the mouse and compare them with the bounds of each stud.
        If the mouse is inside one of the studs bounds and is not
        the 'self.current_widget' selected then it will be made
        the current widget and methods will be called on it
        to highlight it has been selected and to draw the lines etc.
        '''

        for stubNumber in list(self.stubs.values()):

            bound = self.bbox(stubNumber)
            
            if bound[0] < event.x < bound[2] and bound[1] < event.y < bound[3]:

                widget = stubNumber 

                x = [bound[0], bound[2]]
                y = [bound[1], bound[3]]
                middleBoundX = sum(x) / len(x)
                middleBoundY = sum(y) / len(y)
                middleBounds = [middleBoundX, middleBoundY] 

                if self.current_widget != widget:
                    self.current_widget = widget
                    if len(self.pattern.get()) < (18+self.max_length) and str(self.current_widget) not in self.pattern.get()[18:]:
                        self.AddToPattern(self.current_widget)
                        self.ActivateStub(self.current_widget)
                        if self.show_pattern:
                            self.DeleteLine()
                            self.DrawLine(middleBounds)
                    
    def SetupStubs(self, text=False):

        self.X, self.Y = self.STUD_START_X, self.STUD_START_Y

        for stubNum in range(9):

            if text:
                textID = self.create_text(self.X+self.TEXT_DISPLACEMENT, self.Y+self.TEXT_DISPLACEMENT, text=stubNum+1, fill="white", font=('Helvetica 15 bold'))
            else:
                stubButtonID = self.create_image(self.X,self.Y,anchor=tk.NW,image=self.stub)
                self.stubs.update({stubNum: stubButtonID})
            
            self.X += self.STUD_ADD_X
            if self.X == self.STUD_NEXTROWVAL_X:
                self.Y += self.STUD_ADD_Y
                self.X = self.STUD_START_X

        if not text:
            if self.show_numbers:
                self.SetupStubs(True)

    def ClearPattern(self):

        for stub in list(self.stubs.values()):
            self.itemconfig(stub, image=self.stub)
 
        self.pattern.set('Pattern Password: ')
        self.delete(self.line)
        self.hasClicked = False
        self.points = []


if __name__ == '__main__':

    main = tk.Tk()
    main.geometry('500x500')
    main.config(bg='grey')

    title = tk.Label(main, text='Pattern Password', bg=main['bg'], fg='white', font=('Verdana Pro Light', 32, 'underline'))
    title.pack(fill=tk.X, pady=20)

    pattern = PatternPassword(show_pattern=True, show_numbers=True, max_length=9)
    pattern.pack()

    controlFrame = tk.Frame(main, bg='grey')
    controlFrame.pack_propagate(False)
    controlFrame.pack(padx=(50,0), pady=20, ipady=40, fill=tk.X, expand=1)

    passLabel = tk.Label(controlFrame, textvariable=pattern.pattern, font=('Verdana Pro Light', 18), bg='grey', fg='white')
    passLabel.pack(side=tk.LEFT)

    clearPattern = tk.Button(controlFrame, text='Clear', font=('Arial', 20), bg='grey', activebackground='grey', fg='white', activeforeground='white', bd=0, highlightthickness=0, command=pattern.ClearPattern)
    clearPattern.pack(side=tk.LEFT, padx=(20,0), ipadx=20, ipady=3)

    main.mainloop()


Altered the title to just state what the code does
Link
pacmaninbw
  • 26.2k
  • 13
  • 47
  • 114
Loading
Source Link
Jack
  • 41
  • 5
Loading