コード例 #1
0
ファイル: waitingRoom.py プロジェクト: aless80/tantrix
    def startWaitingRoomUI(self, pumpit):
        self.pumpit = True
        if 'pumpit' in locals():
            self.pumpit = pumpit
        cfg.wroom = Tk()
        cfg.wroom.protocol("WM_DELETE_WINDOW", self.quitWaitingRoom)

        """State variables - By using textvariable=var in definition widget is tied to this variable"""
        statusmsg_sv = StringVar() #needed
        entry_sv = StringVar(value = cfg.name)
        #entry_sv.trace("w", lambda name, index, mode, sv=entry_sv: self.changeName(sv))
        chatentry_sv = StringVar(value = "Press enter to chat")

        """Create and grid the outer content frame"""
        content = ttk.Frame(cfg.wroom) #, padding=(5, 5, 12, 0)) 		#Frame in cfg.wroom
        content.grid(column = 0, row = 0, sticky = (N,W,E,S))
        cfg.wroom.grid_columnconfigure(0, weight = 1)
        cfg.wroom.grid_rowconfigure(0, weight = 1)

        """Create the different widgets; note the variables that some widgets are bound to"""
        self.tree = Treeview(content, show="headings", columns=cfg.wroominstance.tree_headers, name = "treeview")
        self.tree.column("#1", minwidth = 100, width = 120, stretch = NO)
        self.tree.column("#2", minwidth = 30, width = 60, stretch = NO)
        self.tree.column("#3", minwidth = 30, width = 50, stretch = YES)
        self.tree.column("#4", minwidth = 30, width = 50, stretch = YES)
        self.tree.column("#5", minwidth = 30, width = 50, stretch = YES)
        namelbl = ttk.Label(content, text="Player name")
        self.nameentry = ttk.Entry(content, bg = 'white', textvariable = entry_sv, name = "nameentry")#, validatecommand=validateIt)
        colorlbl = ttk.Label(content, text="Player color")
        self.colorframe = ttk.Frame(content, name = "colorframe", borderwidth = 1, relief='sunken')
        lbl = ttk.Label(content, text="Send to player:")	#Label on the right
        self.log = Listbox(content, height = 5, bg = 'white', name = "logbox")#, listvariable=cmessagelog		#Listbox with messages
        self.chatAll = ttk.Button(content, text = 'Chat to All', command = self.chatToAll, default = 'active', width = '6',name = "chat")
        self.chatentry = ttk.Entry(content, bg = 'white', foreground = 'gray', textvariable = chatentry_sv, name = "chatentry", selectforeground = 'blue')
        testbtn = ttk.Button(content, text = 'Connections', command = self.test, default = 'active', width = '6', name = "testbtn")
        ready = ttk.Button(content, text = 'Ready', command = self.toggleReadyForGame, default = 'active', width = '6', name = "readybtn")
        solitaire = ttk.Button(content, text = 'Solitaire', command = self.solitaire, default = 'active', width = '6', name = "solitairebtn")
        quit = ttk.Button(content, text = 'Quit', command = self.quitWaitingRoom, default = 'active', width = '6', name = "quitbtn")
        status = ttk.Label(content, textvariable = statusmsg_sv, anchor = W, name = "statuslbl") #Label on the bottom

        def get_tree():
            """Get from the self.tree an item when clicked"""
            idxs = self.tree.item(self.tree.focus())
            vals = idxs['values']
            if len(idxs['values'])==0: return None
            return vals
        """def sortby(tree, col, descending):
            Sort tree contents when a column header is clicked on
            # grab values to sort
            data = [(tree.set(child, col), child) \
                for child in tree.get_children('')]
            # now sort the data in place
            data.sort(reverse=descending)
            for ix, item in enumerate(data):
                tree.move(item[1], '', ix)
            # switch the heading so it will sort in the opposite direction
            tree.heading(col, command=lambda col=col: sortby(tree, col, int(not descending)))
        """
        def showstatus(*args):
            """Called when the selection in the listbox changes;
            Update the status message on the bottom with the new information"""
            list = get_tree()
            if list is None:
                return
            statusmsg_sv.set("Player %s has this status: %s" % (list[0], list[1]))

        # Grid all the widgets
        self.tree.grid(row = 0, column = 0, rowspan = 9, sticky = (N,S,E,W))
        namelbl.grid(row = 0, column = 1, columnspan = 2, sticky = (N,W), padx = 5)
        self.nameentry.grid(row = 1, column = 1, columnspan = 2, sticky = (N,E,W), pady = 5, padx = 5)
        colorlbl.grid(row = 0, column = 3, columnspan = 1, sticky = (N,W), padx = 5)
        self.colorframe.grid(row = 1, column = 3, columnspan = 1, sticky = (N,E,W), pady = 5, padx = 5)
        #testbtn.grid(row = 3, column = 3, columnspan = 1, sticky = E, padx = 5)		#Test Button
        self.log.grid(row = 5, column = 1, columnspan = 3, sticky = (N,S,E,W), padx = 5, pady = 5)   #Listbox with all messages
        self.chatentry.grid(row = 6, column = 1, columnspan = 2, sticky = (N,E), padx = 5, pady = 5)
        self.chatAll.grid(row = 6, column = 3, columnspan = 1, sticky = (N,E), padx = 5, pady = 5)
        ready.grid(row = 7, column = 1, sticky = (W,S), padx = 5, pady = 5)			#
        solitaire.grid(row = 7, column = 2, sticky = (W,S), padx = 5, pady = 5)
        quit.grid(row = 7, column = 3, sticky = (W,S), padx = 5, pady = 5)
        status.grid(row = 9, column = 0, columnspan = 2, sticky = (W,E))

        """Configure content Frame and color Frame"""
        content.grid_columnconfigure(0, weight = 1)
        content.grid_rowconfigure(5, weight = 1)
        h = self.nameentry.winfo_reqheight()
        self.colorframe.configure(height = h, bg = 'red')

        """Set event bindings"""
        self.tree.bind('<<TreeviewSelect>>', showstatus)
        self.nameentry.bind('<Return>', (lambda _: self.askChangeName(self.nameentry)))
        self.nameentry.bind('<FocusOut>', (lambda _: self.askChangeName(self.nameentry)))
        cfg.wroom.bind('<Control-Key-w>', self.quitWaitingRoom)
        cfg.wroom.bind('<Control-Key-q>', self.quitWaitingRoom)
        cfg.wroom.bind('<Control-Key-r>', self.toggleReadyForGame)
        cfg.wroom.bind('<Control-Key-s>', self.solitaire)
        self.chatentry.bind("<Return>",self.chatToAll)
        def chatEntryActive(e = None):
            self.chatentry.config(foreground = 'black')
            self.chatentry.delete(0, 'end')
        def chatEntryInactive(e = None):
            print(self)
            chatentry_sv.set("Press enter to chat")
            self.chatentry.config(foreground = 'gray')
        self.chatentry.bind("<FocusIn>", lambda e: chatEntryActive(e))
        self.chatentry.bind("<FocusOut>", lambda e: chatEntryInactive(e))
        self.colorframe.bind("<ButtonRelease-1>", self.changeColor)

        """Set tooltips on widgets"""
        hover.createToolTip(namelbl, "Type in your name")
        hover.createToolTip(self.nameentry, "Type in your name")
        hover.createToolTip(ready, "Toggle ready state to play tantrix with other players")
        hover.createToolTip(solitaire, "Start a two player game on this computer")
        hover.createToolTip(quit, "Quit Tantrix")
        hover.createToolTip(self.chatentry, "Press enter to send to chat")
        hover.createToolTip(self.chatAll, "Press enter to send to chat")
        hover.createToolTip(self.colorframe, "Click to select your color")
        hover.createToolTip(colorlbl, "Your color")

        """Set the starting state of the interface"""
        statusmsg_sv.set('')
        showstatus()

        """Start main loop for tkinter and Sixpodnet"""
        self.keepLooping = True
        if self.pumpit:
            self.mainLoopWithPump()
        else:
            self.mainLoopWithoutPump()
        return self.quit
コード例 #2
0
ファイル: preSolitaire.py プロジェクト: aless80/tantrix
    def startpreSolitaireUI(self, pumpit):
        self.pumpit = pumpit
        cfg.wroom = Tk()
        cfg.wroom.protocol("WM_DELETE_WINDOW", self.quitpreSolitaire)
        """State variables - By using textvariable=var in definition widget is tied to this variable"""
        entry_sv = StringVar(value = cfg.name)
        entry2_sv = StringVar(value = cfg.opponentname)

        """Create and grid the outer content frame"""
        content = ttk.Frame(cfg.wroom)
        content.grid(column = 0, row = 0, sticky = (N,W,E,S))
        cfg.wroom.grid_columnconfigure(0, weight = 1)
        cfg.wroom.grid_rowconfigure(0, weight = 1)

        """Create the different widgets; note the variables that some widgets are bound to"""
        namelbl = ttk.Label(content, text="Player 1's name")
        self.nameentry = ttk.Entry(content, bg = 'white', textvariable = entry_sv, name = "nameentry")
        namelbl2 = ttk.Label(content, text="Player 2's name")
        self.nameentry2 = ttk.Entry(content, bg = 'white', textvariable = entry2_sv, name = "nameentry2")
        colorlbl = ttk.Label(content, text="Player color")
        self.colorframe = ttk.Frame(content, name = "colorframe", borderwidth = 1, relief='sunken')
        colorlbl2 = ttk.Label(content, text="Player2 color")
        self.colorframe2 = ttk.Frame(content, name = "colorframe2", borderwidth = 1, relief='sunken')
        startbtn = ttk.Button(content, text = 'Start', command = self.quitToGame, default = 'active', width = '6', name = "solitairebtn")
        quit = ttk.Button(content, text = 'Quit', command = self.quitpreSolitaire, default = 'active', width = '6', name = "quitbtn")

        """Grid all the widgets"""
        namelbl.grid(row = 0, column = 0, columnspan = 2, sticky = (N,W), padx = 5)
        colorlbl.grid(row = 0, column = 3, columnspan = 1, sticky = (N,W), padx = 5)
        self.nameentry.grid(row = 1, column = 1, columnspan = 2, sticky = (N,E,W), pady = 5, padx = 5)
        self.colorframe.grid(row = 1, column = 3, columnspan = 1, sticky = (N,E,W), pady = 5, padx = 5)
        namelbl2.grid(row = 2, column = 0, columnspan = 2, sticky = (N,W), padx = 5)
        colorlbl2.grid(row = 2, column = 3, columnspan = 1, sticky = (N,W), padx = 5)
        self.nameentry2.grid(row = 3, column = 1, columnspan = 2, sticky = (N,E,W), pady = 5, padx = 5)
        self.colorframe2.grid(row = 3, column = 3, columnspan = 1, sticky = (N,E,W), pady = 5, padx = 5)
        startbtn.grid(row = 4, column = 3, sticky = (E,S), padx = 5, pady = 5)
        quit.grid(row = 4, column = 2, sticky = (W,S), padx = 5, pady = 5)

        """Configure content Frame and color Frame"""
        content.grid_columnconfigure(0, weight = 1)
        content.grid_rowconfigure(5, weight = 1)
        h = self.nameentry.winfo_reqheight()
        self.colorframe.configure(height = h, bg = cfg.playercolor)
        self.colorframe2.configure(height = h, bg = cfg.opponentcolor)

        """Set event bindings"""
        self.nameentry.bind('<Return>', (lambda _: self.askChangeName(self.nameentry, 1)))
        self.nameentry2.bind('<Return>', (lambda _: self.askChangeName(self.nameentry2, 2)))
        self.nameentry.bind('<FocusOut>', (lambda _: self.askChangeName(self.nameentry, 1)))
        self.nameentry2.bind('<FocusOut>', (lambda _: self.askChangeName(self.nameentry2, 2)))
        cfg.wroom.bind('<Control-Key-w>', self.quitpreSolitaire)
        cfg.wroom.bind('<Control-Key-q>', self.quitpreSolitaire)
        cfg.wroom.bind('<Control-Key-s>', self.quitpreSolitaire)
        self.colorframe.bind("<ButtonRelease-1>", (lambda _: self.changeColor(1)))
        self.colorframe2.bind("<ButtonRelease-1>", (lambda _: self.changeColor(2)))

        """Set tooltips on widgets"""
        #hover.createToolTip(namelbl, "Type in your name and press Enter")
        hover.createToolTip(self.nameentry, "Type in the name for player 1")
        hover.createToolTip(self.nameentry2, "Type in the name for player 2")
        hover.createToolTip(startbtn, "Start a two player game on this computer")
        hover.createToolTip(quit, "Quit Tantrix")
        hover.createToolTip(self.colorframe, "Click to select player 1's color")
        hover.createToolTip(self.colorframe2, "Click to select player 2's color")
        #hover.createToolTip(colorlbl, "Your color")

        """Start main loop for tkinter and Sixpodnet"""
        self.keepLooping = True
        if self.pumpit:
            self.mainLoopWithPump()
        else:
            self.mainLoopWithoutPump()
        return self.quit
コード例 #3
0
ファイル: Gui.py プロジェクト: aless80/tantrix
    def startGameUI(self, wintitle):
        """Determine attributes from player"""
        cfg.gameinprogress = True
        self.win = tk.Tk()
        self.win.protocol("WM_DELETE_WINDOW", self.deleteWindow)
        self.win.wm_title(wintitle)
        self.win.minsize(int(cfg.HEX_COS + (cfg.HEX_SIZE * 2 - cfg.HEX_COS) * 8 + 76),
                         int(math.ceil(cfg.HEX_HEIGHT * 4) + cfg.YTOPPL1 + cfg.HEX_HEIGHT * 1.5 + cfg.HEX_HEIGHT))
        self.win.maxsize(int(cfg.HEX_COS + (cfg.HEX_SIZE * 2 - cfg.HEX_COS) * (cfg.ROWS + 30)),
                         int(math.ceil(cfg.HEX_HEIGHT * (cfg.COLS + 18)) + cfg.YTOPPL1 + cfg.HEX_HEIGHT * 1.5 + cfg.HEX_HEIGHT))
        #Set the window size and get its geometry to dynamically set the positions of its widgets
        win_width = cfg.BOARD_WIDTH + 76 #76 is the width of the buttons on the right
        win_height = cfg.YBOTTOMBOARD + cfg.YTOPBOARD * 2
        self.win.geometry('%dx%d+%d+%d' % (win_width, win_height, 0, 0))
        """Create self.canvas"""
        self.canvas = tk.Canvas(self.win, height = 0, width = 0, name = "canvas")
        """Create main bkgr rectangle in self.canvas"""
        bg_color = "#F1DCFF"
        self.backgroundID = self.canvas.create_rectangle(0, 0, 0, 0,
                                    width = 2, fill = bg_color) #pink-purple
        """Create hexagons on self.canvas"""
        def create_hexagons():
            cfg.hexagon_generator = hg.HexagonGenerator(cfg.HEX_SIZE)
            for row in range(-10, cfg.ROWS + 30):
                for col in range(-10, cfg.COLS + 18):
                    pts = list(cfg.hexagon_generator(row, col))
                    self.canvas.create_line(pts, width = 2)
        create_hexagons()
        """Append canvas on self.win"""
        #self.canvas.grid(row = 1, column = 0, rowspan = 5)
        self.canvas.pack(fill=tk.BOTH, expand=1)

        """Create rectangles to place over self.canvas"""
        #Tiles player 1 on top
        self.textwin1 = self.canvas.create_rectangle(0, 0, 0, 0, width = 2, fill = bg_color, tags = "raised")
        color = cfg.PLAYERCOLORS.index(cfg.playercolor) if cfg.player_num == 1 else cfg.PLAYERCOLORS.index(cfg.opponentcolor)
        color = cfg.PLAYERCOLORS[color + 4]
        self.backgroundTopID = self.canvas.create_rectangle(0, 0, 0, 0, width = 2, fill = color, tags = "raised") #cover the canvas with background for the top tiles
        self.stipple1 = self.canvas.create_rectangle(0, 0, 0, 0, width = 0, tags = "stipple", fill = "") #"#FEFD6C" top yellow
        #Tiles player 2 on bottom
        color = cfg.PLAYERCOLORS.index(cfg.playercolor) if cfg.player_num == 2 else cfg.PLAYERCOLORS.index(cfg.opponentcolor)
        color = cfg.PLAYERCOLORS[color + 4]
        self.backgroundBottomID = self.canvas.create_rectangle(0, 0, 0, 0, width = 2, fill = color, tags = "raised") #cover the canvas with background for the bottom tiles
        self.stipple2 = self.canvas.create_rectangle(0, 0, 0, 0, width = 0, tags = "stipple", fill = "gray", stipple = "gray12")
        self.textwin2 = self.canvas.create_rectangle(0, 0, 0, 0, width = 2, fill = bg_color, tags = "raised")
        #cover canvas on the right
        self.backgroundRightID = self.canvas.create_rectangle(0, 0, 0, 0, width = 2, fill = bg_color, tags = "raised")
        """Buttons"""
        btnwidth = 6
        """Confirm button"""
        self.btnConf = tk.Button(self.win, text = "Confirm\nmove", width = btnwidth, name = "btnConf",
                state = "disabled", relief = "flat", bg = "white", activebackground = "cyan", anchor = tk.W)
        self.btnConf.bind('<ButtonRelease-1>', self.buttonCallback)
        self.btnConf_window = self.canvas.create_window(0, 0, anchor = tk.NW, window = self.btnConf)
        """Reset button"""
        self.btnReset = tk.Button(self.win, text = "Reset\ndeck", width = btnwidth, name = "btnReset", state = "disabled",
                        relief = "flat", bg = "white", activebackground = "cyan")
        self.btnReset_window = self.canvas.create_window(0, 0, anchor = tk.SW, window = self.btnReset)
        self.btnReset.bind('<ButtonRelease-1>', self.buttonCallback)
        """Quit button"""
        self.btnQuit = tk.Button(self.win, text = "Quit", width = btnwidth, name = "btnQuit",
                        relief = "flat", bg = "white", activebackground = "red")
        self.btnQuit_window = self.canvas.create_window(0, 0, anchor = tk.SW, window = self.btnQuit)
        self.btnQuit.bind('<ButtonRelease-1>', self.buttonCallback)
        """Score button"""
        self.btnScore = tk.Button(self.win, text = "Score", width = btnwidth, name = "btnScore", state = "normal",
                        relief = "flat", bg = "white", activebackground = "cyan")
        self.btnScore_window = self.canvas.create_window(1, 1, anchor = tk.W, window = self.btnScore)
        self.btnScore.bind('<ButtonRelease-1>', self.buttonCallback)
        """Text widgets: messages and scores"""
        self.text1 = self.canvas.create_text(0 + 5, 0, text = "", anchor = tk.NW, font = 15, tags = "raised")
        self.text2 = self.canvas.create_text(0, 0, text = "", anchor = tk.SW, font = 15, tags = "raised")
        """Chat"""
        #cfg.chat = tk.Listbox(self.canvas, height = 5, bg = 'white', name = "logbox")#, listvariable=cmessagelog		#Listbox with messages
        #cfg.chatentry = tk.Entry(self.canvas, bg = 'white', foreground = 'gray', textvariable = chatentry_sv, name = "chatentry", selectforeground = 'blue')
        #cfg.chat.grid(row = 5, column = 1, columnspan = 3, sticky = (N,S,E,W), padx = 5, pady = 5)   #Listbox with all messages
        """Store widgets and widget items"""
        cfg.win = self.win
        cfg.canvas = self.canvas
        cfg.textwin1 = self.textwin1
        cfg.stipple1 = self.stipple1
        cfg.stipple2 = self.stipple2
        cfg.textwin2 = self.textwin2
        cfg.text1 = self.text1
        cfg.text2 = self.text2
        #cfg.board = self.board

        cfg.board.message()
        def configure(event):
            """Callback to handle resizing of the main window"""
            win_width, win_height = event.width, event.height
            """Update coordinates used by UI elements"""
            cfg.BOARD_WIDTH = win_width - 76
            cfg.YTOPBOARD = cfg.YTOPPL1 + cfg.HEX_HEIGHT + cfg.BUFFER
            cfg.BOARD_HEIGHT = win_height - (cfg.HEX_HEIGHT * 2.5 + cfg.YTOPPL1 - cfg.BUFFER * 2) - 2# - cfg.HEX_HEIGHT / 4#NEW #2 is ~ the Tk window border
            cfg.YBOTTOMWINDOW = cfg.BOARD_HEIGHT + cfg.HEX_HEIGHT * 2.5 + cfg.YTOPPL1 - cfg.BUFFER * 2# - cfg.HEX_HEIGHT / 2
            cfg.YBOTTOMBOARD = cfg.YBOTTOMWINDOW - cfg.HEX_HEIGHT
            cfg.YBOTTOMPL2 = cfg.YBOTTOMWINDOW - cfg.YTOPPL1
            """Positions of canvas and all canvas items"""
            self.canvas.config(height = win_width, width = win_height)
            self.canvas.coords(self.backgroundID, 0, cfg.YTOPBOARD, cfg.BOARD_WIDTH, cfg.YBOTTOMBOARD)
            self.canvas.coords(self.textwin1, 0, 0, cfg.BOARD_WIDTH, cfg.YTOPPL1)
            self.canvas.coords(self.backgroundTopID, 0, cfg.YTOPPL1, cfg.BOARD_WIDTH, cfg.YTOPBOARD)
            self.canvas.coords(self.stipple1, 0, cfg.YTOPPL1, cfg.BOARD_WIDTH, cfg.YTOPBOARD)
            self.canvas.coords(self.backgroundBottomID, 0, cfg.YBOTTOMBOARD - cfg.YTOPPL1, cfg.BOARD_WIDTH, win_height - cfg.YTOPPL1)
            self.canvas.coords(self.stipple2, 0, cfg.YBOTTOMBOARD - cfg.YTOPPL1, cfg.BOARD_WIDTH, win_height - cfg.YTOPPL1)
            self.canvas.coords(self.textwin2, 0, cfg.YBOTTOMPL2, cfg.BOARD_WIDTH, cfg.YBOTTOMWINDOW)
            self.canvas.coords(self.backgroundRightID, cfg.BOARD_WIDTH, 0, win_width, win_height)
            self.canvas.coords(self.text2, 0 + 5, cfg.YBOTTOMWINDOW)
            """Positions of the buttons"""
            self.canvas.coords(self.btnConf_window, cfg.BOARD_WIDTH + cfg.BUFFER * 2,
                               cfg.YTOPBOARD + cfg.HEX_SIZE * 2)
            self.canvas.coords(self.btnReset_window, cfg.BOARD_WIDTH + cfg.BUFFER * 2,
                               cfg.YTOPBOARD + cfg.HEX_SIZE * 8)#cfg.YBOTTOMBOARD - cfg.HEX_SIZE * 4)
            self.canvas.coords(self.btnQuit_window, cfg.BOARD_WIDTH + cfg.BUFFER * 2,
                               cfg.YBOTTOMBOARD - cfg.HEX_HEIGHT - cfg.HEX_SIZE * 2)
            self.canvas.coords(self.btnScore_window, cfg.BOARD_WIDTH + cfg.BUFFER * 2,
                               cfg.YBOTTOMBOARD - cfg.HEX_HEIGHT - cfg.HEX_SIZE * 6)
            #self.canvas.create_rectangle(0, cfg.YTOPBOARD + cfg.HEX_SIZE, 1000, cfg.YTOPBOARD + cfg.HEX_SIZE * 3, fill="red")
            #self.canvas.create_rectangle(0, cfg.YBOTTOMBOARD - cfg.HEX_HEIGHT / 2, 1000, cfg.YBOTTOMBOARD - cfg.HEX_SIZE * 8, fill="red")
            """Positions of the tiles"""
            cfg.deck.expand()
            """Update window"""
            self.win.update()


        self.canvas.bind("<Configure>", configure)
        """Set the sizes and positions of canvas, widgets and widget items. Create a bogus event to feed in configure"""
        class Event(object):
            pass
        event = Event()
        event.width = win_width
        event.height = win_height
        configure(event)

        """Bind arrows that move the table"""
        self.win.bind('<Left>', lambda event, horiz = 1: cfg.deck.shift(shift_row = horiz))
        self.win.bind('<Right>', lambda event, horiz = -1: cfg.deck.shift(shift_row = horiz))
        self.win.bind('<Down>', lambda event, vert = -1: cfg.deck.shift(shift_col = vert))
        self.win.bind('<Up>', lambda event, vert = 1: cfg.deck.shift(shift_col = vert))
        """Set tooltips on widgets"""
        hover.createToolTip(self.btnQuit, "Quit tantrix")
        hover.createToolTip(self.btnScore, "Show the score as longest line + closed line")
        hover.createToolTip(self.btnReset, "Bring back the moved tiles")
        hover.createToolTip(self.btnConf, "Confirm your move. If the button is disable, something is wrong with your move")
        """Update window"""
        self.win.update()
        self.win.update_idletasks()
        self.win.update()