class Clock: def __init__(self): self.time1 = time.strftime('%H:%M:%S') self.mFrame = Frame() self.mFrame.pack(side=TOP, expand=YES, fill=X) self.watch = Label(self.mFrame, text=self.time1, font=('times', 12, 'bold')) self.watch.pack() self.changeLabel() #first call it manually def changeLabel(self): self.time1 = time.strftime('%H:%M:%S') self.watch.configure(text=self.time1) self.mFrame.after(200, self.changeLabel) #it'll call itself continuously
class App: def __init__(self, master): self.frame = Frame(master) self.frame.pack() self.var = StringVar() self.data_queue = Queue() self.button = Button(self.frame, text=self.var) self.button.pack(side=LEFT) # start the "fetch" thread (just generate data from the clock) self.stop_thread = False self.thread = Thread(target=self.get_data, args=("DATA thread", self.data_queue)) self.thread.start() # when user clicks "close" widget, call self.stop_all() master.protocol("WM_DELETE_WINDOW", self.stop_all ) self.frame.after(500, self.updater) def get_data(self, threadname, q): while not self.stop_thread: a = str(time.time()) self.data_queue.put(a) print(f'get_data: put "{a}" to queue') time.sleep(3) def updater(self): while not self.data_queue.empty(): var = self.data_queue.get() print(f'updater: got {var}') self.frame.after(500, self.updater) # call again after 500ms def stop_all(self): """Catch the "window close event". We must kill the thread and then call normal quit() function. """ self.stop_thread = True self.thread.join() # wait for thread to stop self.frame.quit() # call normal frame quit()
class TicTacToeGUI: ai = None def __init__(self, master): # Initial Frame self.frame = Frame(master) self.frame.pack(fill="both", expand=True) # Board canvas self.canvas = Canvas(self.frame, width=300, height=300) # Symbol selection buttons self.x_button = Button(self.frame, text='Play as X', height=4, command=self.set_player_x, bg='white', fg='black') self.o_button = Button(self.frame, text='Play as O', height=4, command=self.set_player_o, bg='white', fg='red') # Game start button and info box self.start_button = Button(self.frame, text="START", height=4, command=self.start, bg='white', fg='purple') self.info_box = Label(self.frame, text='Tic Tac Toe Game', height=4, bg='white', fg='blue') self.clean_game_board() def start(self): """Sets up game board, starts a tic tac toe game, and a new AI if one doesn't exist. AI makes first move if playing as X """ self.set_game_board() self.game = TicTacToe() self.game.start() if not self.ai: self.ai = TicTacToeAI() if self.ai_symbol == 'x': self.ai_action() def _board(self): """Draws tic tac toe board""" self.canvas.create_rectangle(0, 0, 300, 300, outline="black") self.canvas.create_rectangle(100, 300, 200, 0, outline="black") self.canvas.create_rectangle(0, 100, 300, 200, outline="black") def user_action(self, event): """Attempts to take action that matches user click. If the move is valid, then calls the AI to make the next move. If not, displays the error. """ move_x = event.x // 100 move_y = event.y // 100 move_result = self.game.update(self.player_symbol, (move_x, move_y)) if move_result == "Success": board_x = (200 * move_x + 100) / 2 board_y = (200 * move_y + 100) / 2 if self.player_symbol == 'x': self.draw_x(board_x, board_y) else: self.draw_o(board_x, board_y) if not self.completed(): # Wait a bit before calling the ai, for visual style self.frame.after(500, self.ai_action) else: self.info_box['text'] = move_result def ai_action(self): """Gets the next move from the AI based on current game state, and plays. """ state = self.game.get_board() move = self.ai.get_move(state) move_result = self.game.update(self.ai_symbol, move) if move_result == "Success": board_x = (200 * move[0] + 100) / 2 board_y = (200 * move[1] + 100) / 2 if self.ai_symbol == 'x': self.draw_x(board_x, board_y) else: self.draw_o(board_x, board_y) self.completed() def completed(self): """Checks the game status. If completed, displays the result, and asks whether the player would like to start another game. """ status = self.game.done() if status == 'e': return False message = "Click to start a new game." if status == 't': message = "Tie game. " + message else: message = "Player " + status.upper() + " has won. " + message self.info_box.pack_forget() self.start_button.pack(fill="both", expand=True) self.start_button["text"] = message self.start_button["command"] = self.clean_game_board def draw_x(self, x, y): self.canvas.create_line(x + 20, y + 20, x - 20, y - 20, width=4, fill="black") self.canvas.create_line(x - 20, y + 20, x + 20, y - 20, width=4, fill="black") def draw_o(self, x, y): self.canvas.create_oval(x + 25, y + 25, x - 25, y - 25, width=4, outline="red") def set_game_board(self): """Hides game start buttons, reveals the game board and info box.""" self.start_button.pack_forget() self.x_button.pack_forget() self.o_button.pack_forget() self.canvas.delete(ALL) self.canvas.pack(fill="both", expand=True) self.info_box.pack(fill="both", expand=True) self.canvas.bind("<ButtonPress-1>", self.user_action) self._board() def clean_game_board(self): """Hides game board and label, reveals game start buttons.""" self.canvas.pack_forget() self.info_box.pack_forget() self.start_button.pack_forget() self.x_button.pack(fill="both", expand=True) self.o_button.pack(fill="both", expand=True) def set_player_x(self): self.player_symbol = 'x' self.ai_symbol = 'o' self.start() def set_player_o(self): self.player_symbol = 'o' self.ai_symbol = 'x' self.start()
class GUIMod(threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter self.img_dict = {} self.data_room = [] self.data_role = {'userName': '******', 'state': '\0', 'roomName': '\0'} self.realRoot = None self.root = None self.rootFrame = None self.entryFrame = None def loadImg(self): self.img_dict['1'] = PhotoImage(file='img/咖啡.png') # 空闲 self.img_dict['2'] = PhotoImage(file='img/键盘.png') # 打字中 self.img_dict['3'] = PhotoImage(file='img/在线.png') # 在线 self.img_dict['4'] = PhotoImage(file='img/忙碌.png') # 忙碌 self.img_dict['5'] = PhotoImage(file='img/等待.png') # 给我点时间,我要思考 self.img_dict['6'] = PhotoImage(file='img/快进.png') # 搞快点 self.img_dict['7'] = PhotoImage(file='img/疑问.png') # 令人困惑 self.img_dict['8'] = PhotoImage(file='img/震惊.png') # 令人震惊 self.img_dict['9'] = PhotoImage(file='img/灯泡.png') # 有想法了 self.img_dict['10'] = PhotoImage(file='img/用户.png') # 我是主角 self.img_dict['11'] = PhotoImage(file='img/空白.png') def change_state(self, state_list: list): try: old = self.data_role['state'].split('_') if (self.data_role['state'] == '\0' or self.data_role['userName'] == '\0' or self.data_role['roomName'] == '\0'): return for i in range(len(old)): if (state_list[i] == '-1'): state_list[i] = old[i] new = '_'.join(state_list) if (new == self.data_role['state']): return myHttpRequest(url_changeState, { 'userName': self.data_role['userName'], 'state': new }) except: print('change_state error') def set_line(self, item: dict, frame: Frame): children = frame.winfo_children() children[0].configure(text=item['userName']) mark = item['state'].split('_') children[1].configure(image=self.img_dict[mark[0]]) children[2].configure(image=self.img_dict[mark[1]]) def get_role(self): for i in range(len(self.data_room)): if (self.data_room[i]['userName'] == self.data_role['userName']): self.data_role['state'] = self.data_room[i]['state'] break def rebuild(self): self.rootFrame.destroy() self.rootFrame = Frame(self.root, height=100, width=200) self.rootFrame.grid(row=2, column=0) for i in range(len(self.data_room)): item = self.data_room[i] f = Frame(self.rootFrame) f.grid(row=i, column=0, pady=3, sticky=W) mark = item['state'].split('_') Label(f, text=item['userName'], width=10).grid(row=0, column=0, padx=5) Label(f, image=self.img_dict[mark[0]], width=35).grid(row=0, column=1, padx=5) Label(f, image=self.img_dict[mark[1]], width=35).grid(row=0, column=2, padx=5) if (item['userName'] == self.data_role['userName']): Label(f, image=self.img_dict['10'], width=35).grid(row=0, column=3, padx=5) else: Label(f, image=self.img_dict['11'], width=35).grid(row=0, column=3, padx=5) def report_keyboard(self): if (is_input_flag == True): self.change_state(['2', '-1']) else: self.change_state(['1', '-1']) def update(self): if (self.data_role['userName'] != '\0' and self.data_role['roomName'] != '\0'): self.report_keyboard() data_room_new = myHttpRequest( url_getRoom, {'roomName': self.data_role['roomName']}) if (len(data_room_new) != len(self.data_room)): self.data_room = data_room_new self.rebuild() else: for i in range(len(self.data_room)): if (self.data_room[i] != data_room_new[i]): self.set_line(data_room_new[i], self.rootFrame.winfo_children()[i]) self.data_room = data_room_new self.get_role() self.root.after(1000, self.update) def run(self): self.realRoot = Tk() self.realRoot.attributes('-alpha', 0.75) self.realRoot.title('TRPGHelper') self.realRoot.protocol("WM_DELETE_WINDOW", lambda: os._exit(0)) width = 260 height = 400 img = ImageTk.PhotoImage( Image.open('img/bg.png').resize((width, height))) l = Label(self.realRoot, image=img) l.grid(row=0, column=0) self.root = Frame(self.realRoot) self.root.grid(row=0, column=0) self.loadImg() self.entryFrame = Frame(self.root, height=50, width=120) self.rootFrame = Frame(self.root, height=100, width=120) self.entryFrame.grid(column=0) self.rootFrame.grid(row=2, column=0, sticky=W) ButtonRoomName = Button(self.entryFrame, height=1, text='房间') ButtonUserName = Button(self.entryFrame, height=1, text='用户') EntryRoomName = Entry(self.entryFrame, width=10) EntryUserName = Entry(self.entryFrame, width=10) MenuButtonState = Menubutton(self.entryFrame, text='选择状态', width=10) ms = Menu(MenuButtonState, tearoff=False) ms.add_command(label='我在线哦', command=lambda: self.change_state(['-1', '3'])) ms.add_command(label='真的很忙', command=lambda: self.change_state(['-1', '4'])) ms.add_command(label='等等我!', command=lambda: self.change_state(['-1', '5'])) ms.add_command(label='搞快点!', command=lambda: self.change_state(['-1', '6'])) ms.add_command(label='令人困惑', command=lambda: self.change_state(['-1', '7'])) ms.add_command(label='瓦特法?', command=lambda: self.change_state(['-1', '8'])) ms.add_command(label='懂了悟了', command=lambda: self.change_state(['-1', '9'])) MenuButtonState.configure(menu=ms) def _call_roomNameButton(roomName): self.data_role['roomName'] = roomName def _call_userNameButton_right(): myHttpRequest(url_delUser, {'userName': self.data_role['userName']}) def _call_userNameButton_left(userName): if (userName != self.data_role['userName']): self.change_state(['1', '4']) self.data_role['userName'] = userName try: if (self.data_role['userName'] != '\0'): myHttpRequest(url_register, {'userName': self.data_role['userName']}) myHttpRequest( url_createRoom, { 'userName': self.data_role['userName'], 'roomName': self.data_role['roomName'] }) self.rebuild() except: print('userNameButton error') ButtonRoomName.bind( "<Button-1>", lambda f: _call_roomNameButton(EntryRoomName.get())) ButtonUserName.bind( "<Button-1>", lambda f: _call_userNameButton_left(EntryUserName.get())) ButtonUserName.bind("<Button-3>", lambda f: _call_userNameButton_right()) ButtonRoomName.grid(column=0, row=0, ipady=2, pady=5, ipadx=2, padx=5) ButtonUserName.grid(column=0, row=1, ipady=2, pady=5, ipadx=2, padx=5) EntryRoomName.grid(column=1, row=0, pady=5, ipadx=2, padx=5) EntryUserName.grid(column=1, row=1, pady=5, ipadx=2, padx=5) MenuButtonState.grid(column=2, row=0, pady=5, ipadx=2, padx=5) self.root.after(1000, self.update) self.root.mainloop()
class Gui: def __init__(self): self.root = tkinter.Tk(className="TicTacToe") self.settingsFrame = Frame(self.root, padx=10, pady=10) self.gameFrame = Frame(self.root) self.gameFrame.pack(side=LEFT, expand=True) self.settingsFrame.pack(side=RIGHT, expand=True) self.game = TicTacToe() self.currentCode = self.game.activePlayer self.startPlayer = self.currentCode self.canvas = Canvas(self.gameFrame, width=300, height=300) self.drawGrid() self.createSettingsFrame() self.canvas.bind('<Button-1>', self.clickHandler) self.root.mainloop() def clickHandler(self, event): x, y = event.x, event.y if x < 100 and y < 100: self.drawCode(self.currentCode, 0) elif x > 100 and x < 200 and y < 100: self.drawCode(self.currentCode, 1) elif x > 200 and x < 300 and y < 100: self.drawCode(self.currentCode, 2) elif x < 100 and y > 100 and y < 200: self.drawCode(self.currentCode, 3) elif x > 100 and x < 200 and y > 100 and y < 200: self.drawCode(self.currentCode, 4) elif x > 200 and x < 300 and y > 100 and y < 200: self.drawCode(self.currentCode, 5) elif x < 100 and y > 200 and y < 300: self.drawCode(self.currentCode, 6) elif x > 100 and x < 200 and y > 200 and y < 300: self.drawCode(self.currentCode, 7) elif x > 200 and x < 300 and y > 200 and y < 300: self.drawCode(self.currentCode, 8) def createSettingsFrame(self): Label(self.settingsFrame, text="Score", font="Arial 15", pady=15).pack(side=TOP) Label(self.settingsFrame, text="Player1", font="Arial 10").pack(side=TOP) Label(self.settingsFrame, textvariable=self.game.winsPlayerOne, font="Arial 8").pack(side=TOP) Label(self.settingsFrame, text="Player2", font="Arial 10").pack(side=TOP) Label(self.settingsFrame, textvariable=self.game.winsPlayerTwo, font="Arial 8").pack(side=TOP) def drawGrid(self): self.canvas.create_line(0, 100, 400, 100) self.canvas.create_line(0, 200, 400, 200) self.canvas.create_line(100, 0, 100, 300) self.canvas.create_line(200, 0, 200, 300) self.canvas.create_line(300, 0, 300, 300) self.canvas.pack() def deleteAll(self): for ele in TEXT_IDS: self.canvas.delete(ele) self.game.resetGrid() self.canvas.bind('<Button-1>', self.clickHandler) def drawCode(self, code, pos): arr = DRAWING_POSITIONS[pos] if self.game.checkMoveIfValid(pos, code): TEXT_IDS.append(self.canvas.create_text( arr[0], arr[1], text=self.currentCode, font="Arial 40")) row = self.game.checkWin(self.currentCode) remis = self.game.checkRemis() if remis: self.canvas.unbind('<Button-1>') self.gameFrame.after(2000, self.deleteAll) if row: if row == 1: TEXT_IDS.append(self.canvas.create_line(25, 50, 275, 50)) elif row == 2: TEXT_IDS.append(self.canvas.create_line(25, 150, 275, 150)) elif row == 3: TEXT_IDS.append(self.canvas.create_line(25, 250, 275, 250)) elif row == 4: TEXT_IDS.append(self.canvas.create_line(50, 25, 50, 275)) elif row == 5: TEXT_IDS.append(self.canvas.create_line(150, 25, 150, 275)) elif row == 6: TEXT_IDS.append(self.canvas.create_line(250, 25, 250, 275)) elif row == 7: TEXT_IDS.append(self.canvas.create_line(25, 25, 275, 275)) elif row == 8: TEXT_IDS.append(self.canvas.create_line(25, 275, 275, 25)) self.canvas.unbind('<Button-1>') self.gameFrame.after(2000, self.deleteAll) self.game.switchPlayer() self.currentCode = self.game.activePlayer
class widgets: def __init__(self, main): super().__init__() self.window = main # Set window title self.window.title('Create ReactJs Project') # Set window size self.window.geometry("720x530") #disable resizing self.window.resizable(False, False) # Set window background self.window.configure(bg='#262625') # choose application icon p1 = PhotoImage(file=f'{content.absolutePath}images/logo.png') # Setting icon of master window self.window.iconphoto(False, p1) #checking OS for future use status, result = subprocess.getstatusoutput(f"cd /d images") if status == 0: self.getOS = 'windows' else: self.getOS = 'linux' #create frames self.taskDone = False self.headerFrame = Frame(self.window, background="#262625") self.headerFrame.grid(row=0, column=0, sticky="NSEW", pady=10) self.footerFrame = Frame(self.window) self.createHeader() self.createFirstWindow() def createHeader(self): #creates global header for application self.titleIamge = Canvas(self.headerFrame, width=600, height=120, background="#262625", bd=0, highlightthickness=0) self.titleIamge.grid(row=0, column=0, padx=60) self.img = ImageTk.PhotoImage( Image.open(f"{content.absolutePath}images/titleIcon.png")) self.titleIamge.create_image(285, 80, image=self.img) def createFirstWindow(self): # creates first window self.contentFrame1 = Frame(self.window, background="#262625", highlightbackground="#42B3D2", highlightthickness=1, relief=tk.RAISED, borderwidth=0) self.contentFrame1.grid(row=1, column=0, sticky="NS", pady=10, padx=0) self.createForm() def createForm(self): #creates form for fisrt window # ================================= creation and placement of form labels ========================== # Label(self.contentFrame1, text="Select Project Directory", background="#262625", foreground="#c7c9c7", font=("", 10)).grid(row=0, column=0, sticky=tk.W + tk.N, padx=20, pady=23) Label(self.contentFrame1, text="Enter Project Name", background="#262625", foreground="#c7c9c7", font=("", 10)).grid(row=1, column=0, sticky=tk.W, padx=20, pady=10) Label(self.contentFrame1, text="Enter Project Version", background="#262625", foreground="#c7c9c7", font=("", 10)).grid(row=2, column=0, sticky=tk.W, padx=20, pady=10) Label(self.contentFrame1, text="Enter Project Description", background="#262625", foreground="#c7c9c7", font=("", 10)).grid(row=3, column=0, sticky=tk.W + tk.N, padx=20, pady=10) # ================================= creation and placements of form inputs ========================== # self.e1 = tk.Entry(self.contentFrame1, borderwidth=0, disabledbackground="#343634", disabledforeground="#c7c9c7", font=("Times New Roman", 12)) self.e1.grid(row=0, column=1, columnspan=2, padx=8) self.e1.insert(0, " -- nothing selected --") self.e1.configure(state='disabled') self.e2 = tk.Entry(self.contentFrame1, background="#343634", fg="#c7c9c7", borderwidth=0, font=("Times New Roman", 12)) self.e2.grid(row=1, column=1, columnspan=2, padx=8) self.e3 = tk.Entry(self.contentFrame1, background="#343634", fg="#c7c9c7", disabledbackground="#343634", disabledforeground="#c7c9c7", borderwidth=0, font=("Times New Roman", 12)) self.e3.grid(row=2, column=1, columnspan=2, padx=8) self.e3.insert(0, "1.0.0") self.e3.configure(state='disabled') #textarea for input self.textarea = st.ScrolledText(self.contentFrame1, width=18, height=4, borderwidth=0, highlightthickness=0, font=("Times New Roman", 12), background="#343634", fg="#c7c9c7") self.textarea.grid(row=3, column=1, columnspan=2, padx=6, pady=8) # ================================= creation and placements of action buttons ========================== # #for choose button self.folderimg = PhotoImage( file=f"{content.absolutePath}images/folderIcon.png") self.chooseBtn = tk.Button(self.contentFrame1, background="#262625", image=self.folderimg, borderwidth=0, highlightthickness=0, activebackground="#2b2b2a", cursor="hand1", command=self.selectFolder).grid(row=0, column=3, sticky=tk.W, pady=4) #generating information buttons messages = content.messages self.infoimg = PhotoImage( file=f"{content.absolutePath}images/infoIcon.png") for j in range(0, len(messages)): self.infoBtn = tk.Button( self.contentFrame1, image=self.infoimg, borderwidth=0, highlightthickness=0, background="#262625", activebackground="#2b2b2a", cursor="hand1", command=partial(self.messageWidget, messages[j][0], messages[j][1])).grid(row=j + 1, column=3, sticky=tk.W + tk.N, pady=10) #for submit button self.startimg = PhotoImage( file=f"{content.absolutePath}images/startIcon.png") self.submitBtn = tk.Button(self.contentFrame1, text="Start", borderwidth=0, highlightthickness=0, background="#1d84bf", foreground="white", activebackground="#2b2b2a", cursor="hand1", font=("", 12), command=self.processData).grid(row=5, column=1, sticky=tk.W + tk.E, padx=15, pady=20) # ================================= creation and placements of decorative images ========================== # self.graphicImage = Canvas(self.contentFrame1, width=130, height=140, background="#262625", bd=0, highlightthickness=0) self.graphicImage.grid(row=3, column=3, rowspan=3, padx=60) self.img2 = ImageTk.PhotoImage( Image.open(f"{content.absolutePath}images/graphics1.png")) self.graphicImage.create_image(70, 70, image=self.img2) #---------------- action functions --------------------------------------------------------------------------------# def selectFolder(self): #folder selection widget for form input self.folder_selected = filedialog.askdirectory() self.e1.configure(state='normal') self.e1.delete(0, last=len(self.e1.get())) self.e1.insert(0, self.folder_selected) self.e1.configure(state='disabled') def processData(self): #handling of form data once submitted #storing form data if self.e1.get() == ' -- nothing selected --': self.messageWidget( "Please select project directory.\nThis field can't be empty! ", "warning") elif re.search("[A-Za-z]", self.e2.get()) == None: self.messageWidget( "Empty Or Invalid value in Name field! Also this field requires at least one alphabet", "warning") elif re.search("[A-Za-z]", self.textarea.get("1.0", tk.END)) == None: self.messageWidget( "Empty Or Invalid value in Description field! Also this field requires at least one alphabet", "warning") else: self.dirPath = self.e1.get() self.name = self.e2.get() self.version = self.e3.get() self.description = self.textarea.get("1.0", tk.END) self.path = os.path.join(self.dirPath, self.name) os.mkdir(self.path) self.createSecondWindow() #!important creation of second window # ===================================== ++++++++++++++++++++++++++ =================================== # # ============================================ Second window ======================================== # # ===================================== ++++++++++++++++++++++++++ =================================== # def createSecondWindow(self): #second window initialization #distroy current widgets self.contentFrame1.destroy() self.contentFrame2 = Frame(self.window, background="#262625", highlightbackground="#42B3D2", highlightthickness=1, relief=tk.RAISED, borderwidth=0) self.contentFrame2.grid(row=1, column=0, sticky="NS", pady=10, padx=0) self.createProgressbar() self.createConsole() #cancle button to terminate process self.cancelBtn = tk.Button(self.contentFrame2, borderwidth=0, text="Terminate tasks", highlightthickness=0, background="#bf1d1d", activebackground="#2b2b2a", cursor="hand1", foreground="white", font=("", 12), command=self.cancelTask).grid(row=3, column=0, sticky=tk.W, pady=15, padx=250) self.fetchCommands() def cancelTask(self): #cancle processes if messagebox.askyesno( "Are you sure?", "Do you really wants to cancel installation process?"): self.contentFrame2.destroy() self.cleanDir() self.createFirstWindow() else: pass def updateFrame(self, ind): #frame updater function for gif(loader) self.frame = self.loaderFrames[ind] ind += 1 ind = ind % (len(self.loaderFrames) - 1) self.label.configure(image=self.frame) self.contentFrame2.after(200, self.updateFrame, ind) def createProgressbar(self): #main progressbar components #status label for progressbar self.statusLabel = Label(self.contentFrame2, text="initializing commands..", background="#262625", foreground="#c7c9c7", font=("", 10)) self.statusLabel.grid(row=0, column=0, sticky="NW", padx=55, pady=15) #loader gif self.loaderFrames = [ PhotoImage(file=f'{content.absolutePath}images/loader.gif', format='gif -index %i' % (i)) for i in range(24) ] self.label = Label(self.contentFrame2, background="#262625") self.label.grid(row=0, column=0, sticky="W", padx=25) self.contentFrame2.after(0, self.updateFrame, 0) #progressbar self.p = Progressbar(self.contentFrame2, orient=tk.HORIZONTAL, length=570, mode="determinate", takefocus=True, maximum=100) self.p.grid(row=1, column=0, sticky="E", padx=40, pady=5, ipady=0) def createConsole(self): #console creation #textarea for logs self.showLogsArea = st.ScrolledText(self.contentFrame2, width=61, height=8, borderwidth=0, highlightthickness=0, background="#343634", fg="#68D9B5", font=('arial', 12, 'normal')) self.showLogsArea.grid(row=2, column=0, columnspan=3, pady=10, padx=20) def printLogs(self, log, commandDesc=''): #inserts text in textarea self.statusLabel['text'] = commandDesc self.showLogsArea.configure(state='normal') # Inserting Text which is read only self.showLogsArea.update() last_char_visible = self.showLogsArea.bbox("end-1c") self.showLogsArea.insert(tk.INSERT, log) self.showLogsArea.update() if last_char_visible: self.showLogsArea.see("end") self.showLogsArea.configure(state='disabled') def runCommands(self, command, commandDesc): #core function for running commands #Acquiring and Releasing lock(mutex) to prevent deadlock and synchronization self.lock.acquire() self.printLogs( " > " + command + '\n' + '----------------------------------------------\n', commandDesc) #check for the node version if command == "node -v": result = subprocess.getoutput(f"node -v") result = re.search("v(\d+\.)", result).group() result = result[1:len(result) - 1] if int(result) < 10: self.messageWidget( "Node version 10 or above not detected! first install node with version 10 or above", "error") self.contentFrame2.destroy() os.killpg(os.getpgid(result.pid), signal.SIGTERM) self.cleanDir() self.createFirstWindow() cdCommand = {'linux': 'cd ', 'windows': 'cd /d '} status, result = subprocess.getstatusoutput( f"{cdCommand[self.getOS]}{self.path}&&{command}") if status != 0: self.messageWidget(f"Exit status : {status} \n{result}", "error") self.cleanDir() self.contentFrame2.destroy() #self.cleanDir() self.createFirstWindow() self.p.step(99 // len(self.commandList)) self.printLogs(result + '\n') self.counter += 1 if self.counter >= len(self.commandList): self.generateFiles() self.lock.release() def fetchCommands(self): #fetch commands from commands.json #multithreading synchronization lock self.lock = threading.Lock() #reading json cmdFile = open(f"{content.absolutePath}commands.json", "r") commandJsonObject = json.load(cmdFile) self.commandList = commandJsonObject["linux"]['commands'] self.counter = 0 for cmd in self.commandList: t1 = threading.Thread(target=self.runCommands, args=(cmd, self.commandList[cmd])) t1.daemon = True t1.start() #Here intentionally not joining the processes after t1.start() def messageWidget(self, message, mtype): #message widget if mtype == 'info': messagebox.showinfo("Information", message) elif mtype == "error": messagebox.showerror("Opps An Error Occured", message) elif mtype == "warning": messagebox.showwarning("Warning", message) def generateFiles(self): #generating static files dirPath, name, version, description = self.dirPath, self.name, self.version, self.description projectDir = self.path #======================= generating files with content======================================== filedict = { '.gitignore': content.git, '.prettierrc.json': content.pretty, '.eslintrc.json': content.eslint, 'src/index.html': content.indexHtml, 'src/App.js': content.appJs, 'src/style.css': content.styleCss } os.mkdir(os.path.join(projectDir, 'src')) #os.system(f"mkdir {projectDir}/src") for fil in filedict: with open(f"{projectDir}/{fil}", '+w') as rw: rw.write(filedict[fil]) #==================== updating package file ========= #=== package.json jsonFile = open(f"{projectDir}/package.json", "r") json_object = json.load(jsonFile) jsonFile.close() jsonFile = open(f"{projectDir}/package.json", "w") json_object['name'] = name json_object['version'] = version json_object['description'] = description json_object['scripts'][ 'format'] = "prettier \"src/**/*.{js,html}\" --write" json_object['scripts']['lint'] = "eslint \"src/**/*.{js,jsx}\" --quiet" json_object['scripts']['dev'] = "parcel src/index.html" json.dump(json_object, jsonFile, indent=2) jsonFile.close() #===== package-lock.json jsonFile = open(f"{projectDir}/package-lock.json", "r") json_object = json.load(jsonFile) jsonFile.close() jsonFile = open(f"{projectDir}/package-lock.json", "w") json_object['name'] = name json_object['version'] = version json.dump(json_object, jsonFile, indent=2) jsonFile.close() self.statusLabel['text'] = "installation finished!" self.printLogs("\nHappy Coding \n") self.taskDone = True self.contentFrame2.after(4000, self.createThirdWindow) # ===================================== ++++++++++++++++++++++++++ =================================== # # ============================================ Third window ======================================== # # ===================================== ++++++++++++++++++++++++++ =================================== # def createThirdWindow(self): #initialization self.contentFrame2.destroy() self.contentFrame3 = Frame(self.window, background="#262625", highlightbackground="#42B3D2", highlightthickness=1, relief=tk.RAISED, borderwidth=0) self.contentFrame3.grid(row=1, column=0, sticky="NS", pady=10, padx=0) self.showInfo() def showInfo(self): # ================================= creation and placements of decorative images ========================== # self.tickImage = Canvas(self.contentFrame3, width=40, height=40, background="#262625", bd=0, highlightthickness=0) self.tickImage.grid(row=0, column=0, sticky=tk.W, padx=14) self.img3 = ImageTk.PhotoImage( Image.open(f"{content.absolutePath}images/tick.png")) self.tickImage.create_image(20, 20, image=self.img3) Label(self.contentFrame3, text="React Project has been created successfully", background="#262625", foreground="#c7c9c7", font=("", 12)).grid(row=0, column=0, sticky=tk.W + tk.N, padx=50, pady=13) Label(self.contentFrame3, text=f"Project Directory : {self.path}", background="#262625", foreground="#c7c9c7", font=("", 10)).grid(row=1, column=0, sticky=tk.W + tk.N, padx=20, pady=7) Label(self.contentFrame3, text="npm run format", background="#1a1919", foreground="#68D9B5", width=72, font=("Times New Roman", 12)).grid(row=2, column=0, sticky=tk.W, padx=20, pady=7) Label( self.contentFrame3, text= "> Run this command to format whole project's source code. You can always change this format settings in '.prettierrc.json' file ", background="#262625", foreground="#c7c9c7", font=("", 10), wraplength=616, justify="left").grid( row=3, column=0, sticky=tk.W + tk.N, padx=20, ) Label(self.contentFrame3, text="npm run lint -- --fix", background="#1a1919", foreground="#68D9B5", width=72, font=("Times New Roman", 12)).grid(row=4, column=0, sticky=tk.W, padx=20, pady=7) Label( self.contentFrame3, text= "> Run this command to fix all auto-fixable errors. You can always change lint settings in '.eslintrc.json' file", background="#262625", foreground="#c7c9c7", font=("", 10), wraplength=616, justify="left").grid( row=5, column=0, sticky=tk.W + tk.N, padx=20, ) Label(self.contentFrame3, text="npm run dev", background="#1a1919", foreground="#68D9B5", width=72, font=("Times New Roman", 12)).grid(row=6, column=0, sticky=tk.W, padx=20, pady=7) Label( self.contentFrame3, text= "> Run this command to start development server with babel. Parcel web bundler is pre-configured.", background="#262625", foreground="#c7c9c7", font=("", 10), wraplength=616, justify="left").grid( row=7, column=0, sticky=tk.W + tk.N, padx=20, ) #cancle button to terminate process self.QuitBtn = tk.Button(self.contentFrame3, borderwidth=0, text="Finish", highlightthickness=0, background="#bf1d1d", activebackground="#2b2b2a", cursor="hand1", font=("", 12), foreground="white", command=lambda: self.window.destroy()).grid( row=10, column=0, sticky=tk.W, pady=10, padx=280) def close(self): #warning if messagebox.askyesno("Are you sure?", "Do you really want to exit this application?"): if not self.taskDone: self.cleanDir() self.window.destroy() def cleanDir( self): #cleaning project directory if installation is unsuccessful try: os.system(f"rm -r {self.dirPath}/{self.name}") except: pass
class WorkTimer: def __init__(self, master): # initialize the master self.master = master master.title("SDL Work Timer") # timer counter self.timers = 0 # master dictionary # this will contain indexed dictionaries representing instances of # the work timer. Those dictionaries will contain timers so that the clocks remain separate. ''' { 'notebook1': { 'masterframe': masterframe, # this is the frame containing the entire timer 'timer': timerobject, # this is the timer object, holding timer # functions and numbers 'toggle_button', timer_toggler, # needs to be accessible to alter color 'date': date_label, 'hours': hour_label, 'mins': min_label, 'secs': second_label, 'desc': short_text, 'filename': filename_entry, 'todo': todo_editor, 'done': done_editor, 'notes': notes_editor, }, } ''' self.timer_dict = {} self.timerframe = Frame(self.master, padx=10, pady=10) self.systemframe = Frame(self.master, padx=10, pady=10) self.timer_notebook = Notebook(self.timerframe) self.create_timer(self.timer_dict, self.timer_notebook) # <> system frame elements <> # instantiate system frame elements self.new_timer_button = Button( self.systemframe, width=10, text='New timer', command=lambda: self.create_timer(self.timer_dict, self. timer_notebook)) self.system_label = Label(self.systemframe, text='System:', anchor=W) self.system_output = Label(self.systemframe, text='Loading...', anchor=W) self.system_copyright = Label( self.systemframe, text='Designed and Developed by Stardust Labs', anchor=E) # grid system frame elements self.system_label.grid(row=0, column=0, sticky=W) self.system_output.grid(row=0, column=1) self.new_timer_button.grid(row=0, column=2) self.system_copyright.grid(row=1, column=0, columnspan=3, sticky=E) # grid master elements self.timer_notebook.grid() self.timerframe.grid(row=0, column=0) self.systemframe.grid(row=1, column=0) self.tick() self.system_output.config(text='Ready') def create_timer(self, timer_dict, notebook): # name the timer and instantiate it within the master dictionary self.timers += 1 name = 'notebook' + str(self.timers) self.timer_dict[name] = {} this_timer = self.timer_dict[name] this_timer['id'] = self.timers # initialize dictionary abstractions this_timer['masterframe'] = Frame(notebook, padx=5, pady=5) masterframe = this_timer['masterframe'] this_timer['timer'] = Timer() # frames used to contain timer elements timerframe = Frame(masterframe, padx=10, pady=10) textframe = Frame(masterframe, padx=10, pady=10) # <> Timerframe Elements <> # instantiate timer buttons this_timer['toggle_button'] = Button( timerframe, width=9, text="Start", background='#f00', command=lambda: this_timer['timer'].toggle_timer(this_timer)) timer_reset_button = Button( timerframe, width=9, text='Reset', command=lambda: this_timer['timer'].reset(this_timer)) save_timelog_button = Button( timerframe, width=9, text='Save', command=lambda: self.save_timelog(this_timer)) # container frame for output, will be inline with other items timer_outputframe = Frame(timerframe) # instantiate output items date_label = Label(timer_outputframe, text='Date:', anchor=W) this_timer['date'] = Label(timer_outputframe, text=str(this_timer['timer'].output_date)) hour_label = Label(timer_outputframe, text='Hour:', anchor=W) this_timer['hours'] = Label(timer_outputframe, text=str(this_timer['timer'].output_hour)) min_label = Label(timer_outputframe, text='Min:', anchor=W) this_timer['mins'] = Label(timer_outputframe, text=str(this_timer['timer'].output_min)) sec_label = Label(timer_outputframe, text='Sec:', anchor=W) this_timer['secs'] = Label(timer_outputframe, text=str(this_timer['timer'].output_sec)) # grid output items to timer_outputframe so it can be grid later date_label.grid(row=0, column=0, sticky=W) hour_label.grid(row=1, column=0, sticky=W) min_label.grid(row=2, column=0, sticky=W) sec_label.grid(row=3, column=0, sticky=W) this_timer['date'].grid(row=0, column=1, sticky=E) this_timer['hours'].grid(row=1, column=1, sticky=E) this_timer['mins'].grid(row=2, column=1, sticky=E) this_timer['secs'].grid(row=3, column=1, sticky=E) # instantiate description label and entry description_label = Label(timerframe, text='Desc:', anchor=E) this_timer['desc'] = Entry(timerframe) def change_tab(event, self=self, tab_id=this_timer['id'] - 1, entry=this_timer['desc']): return self.update_tab(event, tab_id, entry) this_timer['desc'].bind('<KeyRelease>', change_tab) # grid timerframe elements this_timer['toggle_button'].grid(row=0, column=0, pady=5) timer_reset_button.grid(row=1, column=0, pady=5) save_timelog_button.grid(row=2, column=0, pady=5) timer_outputframe.grid(row=3, column=0, pady=5) description_label.grid(row=4, column=0, sticky=W) this_timer['desc'].grid(row=5, column=0) # <> Textframe Elements <> filename_frame = Frame(textframe) text_editor_frame = Notebook(textframe) text_system_frame = Frame(textframe) # instantiate filename_frame elements filename_label = Label(filename_frame, text='Filename:') this_timer['filename'] = Entry(filename_frame, width=50) # grid filename_frame elements filename_label.grid(row=0, column=0) this_timer['filename'].grid(row=0, column=1) # instantiate text editors this_timer['todo'] = Text(text_editor_frame, font=('consolas', '10'), width=75, height=17) this_timer['done'] = Text(text_editor_frame, font=('consolas', '10'), width=75, height=17) this_timer['notes'] = Text(text_editor_frame, font=('consolas', '10'), width=75, height=17) # grid text editors and add them to the notebook this_timer['todo'].grid(padx=5) this_timer['done'].grid(padx=5) this_timer['notes'].grid(padx=5) text_editor_frame.add(this_timer['todo'], text='TODO') text_editor_frame.add(this_timer['done'], text='DONE') text_editor_frame.add(this_timer['notes'], text='NOTES') # instantiate text system elements text_save_button = Button(text_system_frame, text='Save Report', command=lambda: self.save_report(this_timer), anchor=E) text_load_button = Button(text_system_frame, text='Load Report', command=lambda: self.load_report(this_timer), anchor=E) # grid text system elements text_save_button.grid(row=0, column=0, padx=5, pady=5, sticky=E) text_load_button.grid(row=0, column=1, padx=5, pady=5, sticky=E) # instantiate notebook delete button timer_delete_button = Button( text_system_frame, text='Delete Timer', command=lambda: self.destroy_timer(this_timer), anchor=E) # grid notebook delete button timer_delete_button.grid(row=0, column=2, padx=5, pady=5, sticky=E) # grid all textframe internal frames filename_frame.grid(row=0, column=0) text_editor_frame.grid(row=1, column=0) text_system_frame.grid(row=2, column=0) # grid submaster frames timerframe.grid(row=0, column=0) textframe.grid(row=0, column=1) # add the timer to the main notebook this_timer['masterframe'].grid() notebook.add(this_timer['masterframe'], text='New Timer') def destroy_timer(self, timer): name = timer['desc'].get() title = 'Deleting timer {timer_name}'.format(timer_name=name) message = 'Are you sure you want to delete {timer_name}?'.format( timer_name=name) destroy = messagebox.askquestion(title, message) if destroy: self.timer_notebook.forget(timer['masterframe']) def save_timelog(self, timer): self.system_update( 'Logging {desc} time...'.format(desc=timer['desc'].get())) description = timer['desc'].get() time = '{date} {h}:{m}:{s} - {desc}\r\n'.format( date=timer['timer'].output_date, h=timer['timer'].output_hour, m=timer['timer'].output_min, s=timer['timer'].output_sec, desc=description, ) with open('timelog.txt', 'a') as timelog: timelog.write(time) self.system_update( '{desc} time logged.'.format(desc=timer['desc'].get())) def save_report(self, timer): self.system_update( 'Saving {desc} report...'.format(desc=timer['desc'].get())) todo_header = '---=== TODO ===---\r\n\r\n' done_header = '---=== DONE ===---\r\n\r\n' notes_header = '---=== NOTES ===---\r\n\r\n' todo_body = timer['todo'].get('1.0', END) done_body = timer['done'].get('1.0', END) notes_body = timer['notes'].get('1.0', END) output_text = '{todo_h}{todo}\r\n\r\n{done_h}{done}\r\n\r\n{notes_h}{notes}'.format( todo_h=todo_header, todo=todo_body, done_h=done_header, done=done_body, notes_h=notes_header, notes=notes_body, ) filename = timer['filename'].get() with open('reports/' + filename + '.txt', 'w') as report: report.write(output_text) self.system_update( '{desc} report saved.'.format(desc=timer['desc'].get())) def load_report(self, timer): self.system_update( 'Loading {file}'.format(file=timer['filename'].get())) filename = timer['filename'].get() with open(filename + '.txt', 'r') as report: input_text = report.read() input_text = input_text.split('---=== DONE ===---') todo_text = input_text[0] input_text = input_text[1].split('---=== NOTES ===---') done_text = input_text[0] notes_text = input_text[1] todo_text = todo_text.replace('---=== TODO ===---', '').replace('\r\n', '') done_text = done_text.replace('\r\n', '') notes_text = notes_text.replace('\r\n', '') timer['todo'].delete('1.0', END) timer['todo'].insert(END, todo_text) timer['done'].delete('1.0', END) timer['done'].insert(END, done_text) timer['notes'].delete('1.0', END) timer['notes'].insert(END, notes_text) self.system_update( '{file} loaded.'.format(file=timer['filename'].get())) def tick(self): for work_timer in self.timer_dict: self.timer_dict[work_timer]['timer'].tick( self.timer_dict[work_timer]) self.systemframe.after(1000, self.tick) def update_tab(self, event, tab_id, entry_widget): updated_title = entry_widget.get() self.timer_notebook.tab(tab_id, text=updated_title) def system_update(self, sys_text): self.system_output.config(text=sys_text)
class Set: def __init__(self, parent): self.parent = parent parent.title("Set") parent.iconbitmap("assets/cardsIcon.ico") #parent.config(bg="#384d9c") ################### Instance Variables ################### self.numbers = {1: "one", 2: "two", 3: "three"} self.colors = {"r": "red", "g": "green", "p": "purple"} self.shadings = {"e": "non", "h": "half", "f": "fully"} self.shapes = {"S": "squiggle", "D": "diamond", "O": "oval"} self.deck = [ Card(w, x, y, z) for w in self.numbers for x in self.colors for y in self.shadings for z in self.shapes ] # field is defined at the bottom since it requires the tk frame it's in self.helds = set() self.justDealt = False self.solutions = [] self.puzField = [] self.puzSols = [] self.score = 0 self.setsOnBoard = 0 self.gameState = 0 #0 is no game currently being played, 1 is solitaire, 2 is puzzle self.startTime = 0 self.imgDict = { str(w) + x + y + z: PhotoImage(file="assets/" + str(w) + x + y + z + ".png") for w in self.numbers for x in self.colors for y in self.shadings for z in self.shapes } self.empty = PhotoImage(file="assets/empty.png") ########################## GUI ########################## self.gameFrame = Frame(parent) self.fieldFrame = LabelFrame(self.gameFrame, text="") # the foundSets LabelFrame for puzzle mode will also go here self.lowerFrame = Frame(parent) self.foundSets = LabelFrame(self.lowerFrame, text="Sets Found") self.messageFrame = Frame(self.lowerFrame) self.message = Label(self.messageFrame, text="") self.msgUpdate = self.messageFrame.after(1, self.resetMessage, "") self.scoreboard = Label(self.lowerFrame, text="") self.deckStatus = Label(self.lowerFrame, text="") self.solsButton = Button(self.lowerFrame, text="Show current solutions.", command=self.showSolutions) self.field = [[ Spot( i, j, None, Button(self.fieldFrame, image=self.empty, bg="white", command=lambda i=i, j=j: self.bClick(i, j))) for j in range(7) ] for i in range(3)] #This is the game board, 21 spots max. A set is unavoidable with 20 spots. It is redefined in the startSolit method. #For puzzle mode the field will have only 4 columns and a seperate widget showing the found sets will be gridded into the fieldFrame ___TODO____ self.solitButton = Button(self.lowerFrame, text="Start/Restart a Solitaire Game", command=lambda: solit.start(self)) self.puzzleButton = Button(self.lowerFrame, text="Start/Restart a Puzzle Game", command=lambda: puz.start(self)) self.gameFrame.pack() self.fieldFrame.grid(row=0, column=0, padx=40) #.grid(row=0, column=0) for y in range( 3 ): #grid 12 of the 21 possible field buttons, additional buttons will get gridded in only if they have a card for x in range(4): self.field[y][x].button.grid(row=y, column=x) self.lowerFrame.pack() self.messageFrame.pack() self.message.pack() self.scoreboard.pack() self.deckStatus.pack() self.solsButton.pack() self.solitButton.pack() self.puzzleButton.pack(pady=(0, 40)) ######################## METHODS ######################## def gameOver(self): timeDif = datetime.datetime.now( ) - self.startTime # datetime timedelta object finTime = "Finished in {} minute{}, {}.{} second{}.".format( timeDif.seconds // 60, "s" if timeDif.seconds // 60 != 1 else "", timeDif.seconds % 60, str(timeDif) [8: 11], #this truncates to milliseconds, doesn't round, shouldn't ever really be an issue "s" if timeDif.seconds > 0 else "") for x in self.field: for y in x: y.button.config(state=DISABLED) if self.gameState == 1: self.message.config(text="No sets and deck is empty, game over! " + finTime) else: self.message.config(text="All sets found, game over! " + finTime) self.gameState = 0 def start_shared(self): self.deck = [ Card(w, x, y, z) for w in self.numbers for x in self.colors for y in self.shadings for z in self.shapes ] self.helds = set() self.score = 0 if self.buttonsInField() != 12: for button in self.fieldFrame.winfo_children(): button.grid_forget() #ungrid the buttons in the field for x in range( 3 ): #grid 12 of the 21 possible field buttons, additional buttons will get gridded in only if they have a card for y in range(4): self.field[x][y].button.grid(row=x, column=y) for row in self.field: for spot in row: spot.card = None spot.button.config(state=NORMAL) self.startTime = datetime.datetime.now() def sets_finder(self, cardsList): self.solutions = [] self.setsOnBoard = 99 sets = [] for i in cardsList: for j in cardsList: if j != i: for k in cardsList: if k != j and k != i and { i, j, k } not in sets and self.is_set([i, j, k]): sets.append({i, j, k}) self.solutions.append({i, j, k}) if self.gameState == 1: self.setsOnBoard = len(sets) solit.sets_finder_handler(self, self.setsOnBoard) if self.gameState == 2: return sets def is_set(self, givenCards, extraInfo="no"): """takes a set of exactly 3 card objects, extraInfo if called from having full helds in checkSet()), not if called from setsFinder()""" attrSwitcher = { "number": {x.number for x in givenCards}, "color": {x.color for x in givenCards}, "shading": {x.shading for x in givenCards}, "shape": {x.shape for x in givenCards} } if extraInfo == "yes": for attribute in attrSwitcher: if len(attrSwitcher.get(attribute)) == 2: falsRay = [False, "two of", "one of", attribute] notSetAtts = [ eval( "self." + attribute + "s.get(card." + attribute + ")", { "self": self, "card": card }) for card in givenCards ] #the above is hacky but the easiest way to reconcile with the dictionaries print(notSetAtts) for x in notSetAtts: if notSetAtts.count(x) == 2 and x not in falsRay: falsRay[1] = str(x) if notSetAtts.count(x) == 1: falsRay[2] = str(x) print(falsRay) return falsRay #to show reason why it's not a set return [True] else: for attribute in attrSwitcher: if len(attrSwitcher.get(attribute)) == 2: return False return True def checkSet( self ): #TODO ___ this is convoluted, maybe store spots in helds instead of cards? infoRay = self.is_set(self.helds, extraInfo="yes") if infoRay[0]: if self.gameState == 1: solit.found_a_set(self) else: puz.found_a_set(self) else: #Make a grammatically correct string explaining why helds is not a set. Handles a few possible cases. #REMEMBER infoRay = [False, "two of", "one of", attribute] self.messageFrame.after_cancel(self.msgUpdate) whyNot = "two cards {} {} and the other {} {}." badAttr = infoRay[3] whyNotSwitcher = { "number": " symbol", "color": "", "shading": "-shaded", "shape": "" } switchText = whyNotSwitcher.get(badAttr) isNums = badAttr == "number" isShapes = badAttr == "shape" edgeCase = False if isShapes: for card in self.helds: print(self.shapes[card.shape]) #print(infoRay[2]) if self.shapes[card.shape] == infoRay[ 2] and card.number == 1: #if the bat attr is shapes and the "one off" is a singular shape edgeCase = True print("edge case") break if edgeCase: part4 = "a{} ".format("n" if infoRay[2] == "oval" else "") + infoRay[2] + switchText elif isNums and infoRay[2] != "one" or isShapes: part4 = infoRay[2] + switchText + "s" else: part4 = infoRay[2] + switchText self.message.config(text="Not a set, " + whyNot.format( "have" if isNums or isShapes else "are", infoRay[1] + switchText + "s" if isNums and infoRay[1] != "one" or isShapes else infoRay[1] + switchText, "has" if isNums or isShapes else "is", part4)) for x in self.field: for y in x: if y.card in self.helds: y.button.config( bg="white" ) #this is one reason to make helds spots instead of cards self.msgUpdate = self.messageFrame.after( 5000, self.resetMessage, "There are " + str(self.setsOnBoard) + " sets on the board right now." if self.gameState == 1 else str(self.score) + " of 6 sets found.") self.helds = set() ########################################################################################## def bClick(self, i, j): if self.field[i][j].card not in self.helds: self.field[i][j].button.config(bg="orange") self.helds.add(self.field[i][j].card) if len(self.helds) > 2: self.checkSet() else: self.field[i][j].button.config(bg="white") self.helds.remove(self.field[i][j].card) def dealTo(self, i, j): self.field[i][j].card = self.deck.pop() self.update_card(i, j) def update_card(self, i, j): """updates the button image""" self.field[i][j].button.config( bg="white" ) #this is redundant for some calls but better than putting it everywhere self.field[i][j].button.config( image=self.imgDict[str(self.field[i][j].card.number) + self.field[i][j].card.color + self.field[i][j].card.shading + self.field[i][j].card.shape]) def showSolutions(self): msgText = "" for sol in self.solutions: for card in sol: msgText += str.capitalize(self.numbers[card.number] + " " + self.colors[card.color] + " " + self.shadings[card.shading] + "-shaded " + self.shapes[card.shape] + ", ") msgText = msgText[:-2] msgText += ".\n" self.message.config(text=msgText) def buttonsInField(self): i = 0 for x in self.field: for y in x: if y.button.winfo_ismapped(): i += 1 return i def resetMessage(self, msgText): """This only needs to be a separate method for timed event handling purposes""" self.message.config(text=msgText)