Label, LabelFrame, Frame, Entry, Button, Listbox, root, toplevel, Message ; plus using propagate()
Originally we though about trying to do just three examples covering all the widgets and this was one of them. Turned out they would be too hard for new users to follow so we compromised – on about 15. The point is when you run it this looks pretty simple but there is a fair amount going on under the surface. The fantasy here is you have a bunch of players to split into two equally matched teams. You can move players from one team to another, delete players entirely and add new players. It starts with an intro screen, then when the user dismisses the intro screen it puts up a message that has to be acknowledged before you can play with the main application.
#Multiple Widget Demo: Label, LabelFrame, Frame, Entry, Button, Listbox, root, toplevel ; plus using propagate() #This top section is just wikipython standard tkinter set up header code 2 from tkinter import * root = Tk() root.attributes('-fullscreen', True) root.configure(background='DarkSlategray4') scrW = root.winfo_screenwidth() scrH = root.winfo_screenheight() workwindow = str(1024) + "x" + str(768)+ "+" +str(int((scrW-1024)/2)) + "+" +str(int((scrH-768)/2)) top1 = Toplevel(root, bg="light blue") top1.geometry(workwindow) top1.title("Top 1 - Workwindow") top1.attributes("-topmost", 1) # make sure top1 is on top to start root.update() # but don't leave it locked in place top1.attributes("-topmost", 0) # in case you use lower or lift #exit button - note: uses grid b3=Button(root, text="Egress", command=root.destroy) b3.grid(row=0,column=0,ipadx=10, ipady=10, pady=5, padx=5, sticky = W+N) #top1.grid_propagate(0) #____________________________ # The purpose here is NOT code optimization but widget demonstration! # One key thing nobody tells you - usual default is 1 character = 8 pixels # and you will need to know this because frame widgets work on pixel widths # whereas text based widgets (like labels) work on character widths and line heights # VARIABLES AND STUFF l1HeadTxt=StringVar() #control varialbles - global in nature l1HeadTxt.set("Team ONE List") l2HeadTxt=StringVar() l2HeadTxt.set("Team TWO List") team1=["Andrea","Bob","Valerie","Charlie","Terry", "Meredith", "Sharon","Larry", "Vivion", "Donna"] #Teams would be stored on and retrieved team2=["Dave", "Betty","Eric","Cathy","John","Liz", "Ben","Terri","Andrew", "Mike"] #from disk in a real situation. newEntry=StringVar() newEntry.set("") c1, c2, c3, c4, c5, c6="gray90","navy","red4","white","linen","dark green" #makes it easy to change color scheme player=StringVar() player.set("") # for demo I put relief around Frames and LabelFrames to revel the screen plan (done in Excel) top1.configure(bg=c1) # but in practice set master and frames all to the same background color textOfMsg= ''' Welcome to multiple widget demo: REC TEAM MAKER This little demo app includes examples of the following widgets: Label, LabelFrame, Frame, Entry, Button, Listbox, root, toplevel, ...and yours truly - Message. Message is like a multi-line label with a few facilities for breaking lines, but not really for managing text, etc. For that, you will need to use a Text widget. And don't confuse me with a Messagebox - you won't find that trashy, communicative cousin here. Messagebox is in a different demo. Now, when you are ready, click the button below that says "Move On" and, alas, I will be gone for good. Have a nice day.''' # SET UP LABELFRAME CLASS TO BUILD 7 FRAMES ACROSS THE TOP class myLabelFrame(LabelFrame): #Using LabelFrames to force define our design def __init__(self,width,height,relief,background,row,column): global selfhold selfhold=self self.width=width self.height=height self.relief=relief self.background=background self=LabelFrame(top1,width=self.width,height=self.height,relief=self.relief,bg=self.background) self.propagate(0) if column==1: #make a side trip to stuff in a couple of column headers Label(self, text=l1HeadTxt.get(), font="Arial 12 bold", bg=c2, fg=c4).pack() if column==5: Label(self, text=l2HeadTxt.get(), font="Georgia 13 bold", bg=c3, fg=c4).pack(expand=True, fill=BOTH) self.grid(row=row, column=column) #the key to propagate, don't grid the container until # the labels are packed into it. # FUNCTIONS AND STUFF - these are the "verbs" of Python as opposed to the "nouns" of class definitions def t1DelSel(): # these should all be pretty self explanatory - tried to pick names that Team1.delete(ANCHOR) # kind of explain function - Team 1 Delete Selection = t1DelSel def t2DelSel(): Team2.delete(ANCHOR) def bl1tol2(): # button to transfer from List 1 to List 2 = bl1tol2 player=Team1.get(ACTIVE) player2move=Team1.curselection() Team2.insert(END, player) Team1.delete(ACTIVE) def bl2tol1(): player=Team2.get(ACTIVE) player2move=Team2.curselection() Team1.insert(END, player) Team2.delete(ACTIVE) def e2T1(): # e is for entry; e2T1= move entry value to Team 1, then clear entry player=e.get() if player=="": player="Unknown" Team1.insert(END, player) e.delete(0,END) #all caps usually indicates a dedicated constant defined in Python/tkinter def e2T2(): player=e.get() if player=="": player="Unknown" Team2.insert(END, player) e.delete(0,END) # CREATE AND POST THE WIDGETS IN OUR SCREEN PLAN # Set up the columns and list headers colwidths=[50,287,150,50,150,287,50] # would have put these up with the variable but headColors=[c1,c2,c1,c1,c1,c2,c1] # it is easier to see and understand having them here row1, lfheight, relief = 0, 40, GROOVE #lf stands for "LabelFrame" - to finish chg groove to flat for colcount in range(7): # ...and just like that, our columns are set up myLabelFrame(colwidths[colcount],lfheight, relief, headColors[colcount], 0, colcount) # Put a tittle header in NOTE - this demos you can grid one widget on top of another title=Label(top1, text="Rec Team Maker", bg=c6, fg=c1, font='arial 11 bold') title.grid(row=0, column=2, columnspan=3, sticky=E+W) # Put in sidebars and middle bar ...and boom - our row structure is set lfLeft1= LabelFrame(top1, width=50, bg=c1, height=230).grid(row=1, column=0, rowspan=1, sticky=N) lfLeft2= LabelFrame(top1, width=50, bg=c1, height=230).grid(row=2, column=0, rowspan=1, sticky=N) lfLeft3= LabelFrame(top1, width=50, bg=c1, height=268).grid(row=3, column=0, rowspan=2, sticky=N) lfRight= LabelFrame(top1,width=50, bg=c1, height=728).grid(row=1, column=6, rowspan=4, sticky=N) lfMid = LabelFrame(top1, width=50, bg=c1, height=460).grid(row=1, column=3, rowspan=2, sticky=N) # Team1 (leftside) listbox and delete button T1frame=Frame(top1,height=690, width=287, relief=SUNKEN, bd=8) T1frame.grid_propagate(0) Team1=Listbox(T1frame, relief=FLAT, width=286, height=33, font="Verdana 14", bg=c5) Team1.grid(row=0, column=0) for player in team1: Team1.insert(END, player) T1frame.grid(row=1, column=1, rowspan=3) Bt1Del=Button(top1, width=35, text="Remove Selected Player", bg=c2, fg=c4, command=t1DelSel) Bt1Del.grid( row=4, column=1) # Team2 (rightside) listbox and delete button T2frame=Frame(top1, height=690, width=287, relief=SUNKEN, bd=8) T2frame.grid_propagate(0) Team2=Listbox(T2frame, relief=FLAT, width=286, height=33, font="Georgia 15",bg=c5) Team2.grid(row=0, column=0) for player in team2: Team2.insert(END, player) T2frame.grid(row=1, column=5, rowspan=3) Bt2Del=Button(top1, width=35, text="Remove Selected Player", bg=c3, fg=c4, command=t2DelSel) Bt2Del.grid( row=4, column=5, rowspan=3) # Button to move selection Team 1 to Team2 stuffed in frame for sizing selFmLfTop=LabelFrame(top1, relief=GROOVE, width=150, height=230, bg=c1, bd=5) selFmLfTop.pack_propagate(0) B1to2=Button(selFmLfTop, width=15, height=3, bg=c2, fg=c4, command=bl1tol2, text="Move Selection\nto Team 2 ->", relief=RAISED, bd=5) B1to2.pack() selFmLfTop.grid(row=1, column=2, sticky=S) # Button to send a new player to a team selFmLfBtm=LabelFrame(top1, relief=GROOVE, width=150, height=230, bg=c1, bd=5) selFmLfBtm.pack_propagate(0) NewT1Item=Button(selFmLfBtm, width=15, height=3, bg=c2, fg=c4, command=e2T1, text="Move New\n Player\nto Team 1", relief=RAISED, bd=5) NewT1Item.pack(side="bottom") selFmLfBtm.grid(row=2, column=2, sticky=N) # Button to move selection Team 2 to Team1 stuffed in frame for sizing selFmRtTop=LabelFrame(top1, relief=GROOVE, width=150, height=230, bg=c1, bd=5) selFmRtTop.pack_propagate(0) B2to1=Button(selFmRtTop, width=15, height=3, bg=c3, fg=c4, command=bl2tol1, text="Move Selection\n<- to Team 2", relief=RAISED, bd=5) B2to1.pack() selFmRtTop.grid(row=1, column=4, sticky=S) # Button to send a new player to a team selFmRtBtm=LabelFrame(top1, relief=GROOVE, width=150, height=230, bg=c1, bd=5) selFmRtBtm.pack_propagate(0) NewT2Item=Button(selFmRtBtm, width=15, height=3, bg=c3, fg=c4, command=e2T2, text="Move New\n Player\nto Team 2", relief=RAISED, bd=5) NewT2Item.pack(side="bottom") selFmRtBtm.grid(row=2, column=4, sticky=N) # Create Frame for entry label and entry widget eframe=Frame(top1, relief=GROOVE, width=351, height=230, bg=c1, bd=5) #Frame or LabelFrame - either one works here eframe.grid_propagate(0) eframe.grid(row=3, column=2, columnspan=3, stick=E+W) elabel=Label(eframe, width=30, height=3, text= "ENTER NEW PLAYER NAME BELOW", bg=c6, fg=c4, font="arial 11 bold", anchor="w") elabel.grid(row=0, column=0, sticky=E+W) #undersized the width a little in fine tuning - looks better in relief e=Entry(eframe, bd=7, cursor="man", font="Georgia 11 bold", relief=RIDGE, bg="blanched almond") e.focus_set() e.grid(row=1,column=0, sticky=W+E) # Build and deploy screens 2 and 3 # This is a message to explain a feature of the form top3=Toplevel(root, bg='black') top3.attributes("-topmost", 0) top3.geometry(str(500) + "x" + str(400)+ "+" +str(int((scrW-500)/2)) + "+" +str(int((scrH-400)/2))) top3.lower(belowThis=None) # This is the opening message of the app top2= Toplevel(root, bg="burlywood2") top2.geometry(workwindow) top2.attributes("-topmost", 1) # Have to put these functions in place before they are needed def top3Gone(self): top1.attributes("-topmost", 1) e.focus_set() top3.destroy() root.update() def notice(): top2.attributes("-topmost", 0) top3.lift(aboveThis=None) t3lab.focus_set() top2.destroy() root.update() # Intro Screen - top2 - continue msg=Message(top2, bg="wheat1", text=textOfMsg, relief=GROOVE, font="Georgia 14") msg.pack(padx=50, pady=50) B1= Button(top2, text= "Be Gone 'o Message\nand reveal thy true purpose.", height=2, command=notice) B1.pack(pady=20) B1.focus_set() # Popup message with text gets focus when opening screen is destroyed t3lab= Label(top3, height=6, text="If no player is selected, \n the first player is \nmoved to other team.\n\nPress any key to continue.") t3lab.pack(pady=10) t3lab.bind("<Key>", top3Gone) t3lab.bind("<1>", top3Gone) top3.focus_set #____________________________ root.mainloop()