2020年9月12日星期六

73 《零基礎入門學習Python》筆記 第073講:GUI的終極選擇:Tkinter10

《零基礎入門學習Python》第073講:GUI的終極選擇:Tkinter10


我們不難發現,幾乎每一個應用程序都有一些相同的地方,比如說:標題欄、狀態欄、邊框、滾動條、工作區。還有的就是菜單。
傳統的菜單有大家熟悉的File,Edit,Help等,點開之後,是下拉菜單,今天我們就來學習使用tkinter 如何製作這樣子的菜單。tkinter 提供了一個叫做Menu 的組件,主要是用於實現頂級菜單、下拉菜單和彈出菜單。
由於該組件是由底層代碼來實現的,並且已經優化好了,我們這裡不建議你自行通過按鈕或者其他的組件來實現菜單的功能,我知道你可以。但是Python的開發原則就是有得用,你就別自己瞎搞。我說的是正式開發中,在學習中,沒事搞一搞是可以讓我們學習到更多知識的。
我們先來實現創建一個頂級菜單:
  1. import tkinter as tk
  2. root = tk.Tk()
  3. def callback():
  4. print("你好~")
  5. menubar = tk.Menu(root)
  6. menubar.add_command(label = "hello", command = callback)
  7. menubar.add_command(label = "quit", command = root.quit)
  8. root.config(menu = menubar)#把创建的 menubar 与根窗口的 menu 绑定,才会显示菜单
  9. root.mainloop()
我們接下來實現下拉菜單,我們要實現下拉菜單,例如我們點一下hello,它會出來很多其他的選項,而不是執行一個命令,方法也是大同小異的,只是說下拉菜單我們把它們添加到主菜單上,而不是窗口上,我們舉例說明:
  1. import tkinter as tk
  2. root = tk.Tk()
  3. def callback():
  4. print("你好~")
  5. menubar = tk.Menu(root)
  6. ###创建文件菜单
  7. filemenu = tk.Menu(menubar)
  8. filemenu.add_command(label = "打开", command = callback)
  9. filemenu.add_command(label = "保存", command = callback)
  10. #我们还创建下拉菜单之间的分割线
  11. filemenu.add_separator()
  12. filemenu.add_command(label = "退出", command = root.quit)
  13. #创建级联菜单
  14. menubar.add_cascade(label = "文件", menu = filemenu)
  15. ###创建编辑菜单
  16. editmenu = tk.Menu(menubar, tearoff = False) #tearoff = False ,就是没有下拉菜单顶部的虚线
  17. editmenu.add_command(label = "剪切", command = callback)
  18. editmenu.add_command(label = "拷贝", command = callback)
  19. editmenu.add_command(label = "粘贴", command = root.quit)
  20. #创建级联菜单
  21. menubar.add_cascade(label = "编辑", menu = editmenu)
  22. root.config(menu = menubar)#把创建的 menubar 与根窗口的 menu 绑定,才会显示菜单
  23. root.mainloop()
我們來說一下tearoff 的作用,tearoff 默認為True,顯性特點就是有一點虛線,當我們點擊這一條虛線時:(菜單可以被撕下(tearoff))
我們再來說一個彈出菜單:
  1. import tkinter as tk
  2. root = tk.Tk()
  3. def callback():
  4. print("你好~")
  5. menubar = tk.Menu(root)
  6. menubar = tk.Menu(menubar)
  7. menubar.add_command(label = "撤销", command = callback)
  8. menubar.add_command(label = "退出", command = root.quit)
  9. frame = tk.Frame(root, width =512, height = 512)
  10. frame.pack()
  11. def popup(event):
  12. menubar.post(event.x_root, event.y_root)
  13. frame.bind("<Button-3>", popup) #<Button-3>就是鼠标右键
  14. root.mainloop()
運行後,點擊鼠標右鍵:
菜單不僅可以添加我們普通的命令行(add_command),事實上我們還可以添加像Checkbutton(多選按鈕)和Radiobutton(單選按鈕)這樣子的菜單項,它們的用法就和Checkbutton 和Radiobutton 組件是差不多的。
我們繼續創建一個帶有checkbutton 和radiobutton 的菜單給大家看看:
  1. import tkinter as tk
  2. root = tk.Tk()
  3. def callback():
  4. print("你好~")
  5. menubar = tk.Menu(root)
  6. openVar = tk.IntVar()
  7. saveVar = tk.IntVar()
  8. quitVar = tk.IntVar()
  9. filemenu = tk.Menu(menubar, tearoff = False)
  10. filemenu.add_checkbutton(label = "打开", command = callback, variable = openVar)
  11. filemenu.add_checkbutton(label = "保存", command = callback, variable = saveVar)
  12. filemenu.add_separator()
  13. filemenu.add_checkbutton(label = "退出", command = root.quit, variable = quitVar)
  14. menubar.add_cascade(label = "文件", menu = filemenu)
  15. editVar = tk.IntVar()
  16. editmenu = tk.Menu(menubar, tearoff = False)
  17. editmenu.add_radiobutton(label = "剪切", command = callback, variable = editVar, value = 1)
  18. editmenu.add_radiobutton(label = "拷贝", command = callback, variable = editVar, value = 2)
  19. editmenu.add_radiobutton(label = "粘贴", command = root.quit, variable = editVar, value = 3)
  20. menubar.add_cascade(label = "编辑", menu = editmenu)
  21. root.config(menu = menubar)
  22. root.mainloop()
我們接下來介紹一個新的組件Menubutton。
Menubutton 組件是一個與Menu 組件相關聯的按鈕,(事實上就是Menu + Button),它可以放在窗口中的任意位置,並且在被按下時彈出下拉菜單。
這個組件是有一些歷史意義的,因為剛開始是沒有頂級菜單的,那麼就用Menubutton 實現一個個按鈕在上面,點一個按鈕就出現菜單。
現在該組件適用於你希望菜單按鈕出現在其他位置的時候。
舉個例子:
  1. import tkinter as tk
  2. root = tk.Tk()
  3. def callback():
  4. print("你好~")
  5. mb = tk.Menubutton(root, text = "点我", relief = "raised")
  6. mb.pack()
  7. filemenu = tk.Menu(mb, tearoff = False)
  8. filemenu.add_command(label = "打开", command = callback)
  9. filemenu.add_command(label = "保存", command = callback)
  10. filemenu.add_separator()
  11. filemenu.add_command(label = "退出", command = root.quit)
  12. mb.config(menu = filemenu)
  13. root.mainloop()
我們接下來介紹一下Optionmenu(選擇菜單)。
OptionMenu(選擇菜單)事實上是下拉菜單的改版,它的發明彌補了Listbox 組件無法實現下拉列錶框的遺憾。因為事實上創建一個選擇菜單,就跟一個下拉列錶框是一個道理的。我們來看一下它實現的效果就知道了。
  1. import tkinter as tk
  2. root = tk.Tk()
  3. variable = tk.StringVar()
  4. variable.set("one")
  5. w = tk.OptionMenu(root, variable, "one", "two", "three")
  6. w.pack()
  7. root.mainloop()
最後,演示一下,如何將很多項添加到選擇菜單中,就是很多選項在一個列表或者元組中,如何將他們添加到OptionMenu 菜單中,
  1. import tkinter as tk
  2. OPTIONS = [
  3. "Wuhan",
  4. "Beijing",
  5. "Shanghai",
  6. "Tianjin",
  7. "Aomen",
  8. "Xianggang",
  9. "Hankou"
  10. ]
  11. root = tk.Tk()
  12. variable = tk.StringVar()
  13. variable.set(OPTIONS[0])
  14. w = tk.OptionMenu(root, variable, *OPTIONS) #*号有一个解包的功能,如果没有 * 号,就把整个列表当做一个选项了
  15. w.pack()
  16. root.mainloop()
注意:星號(*)作為形參的時候是起到“打包”的作用,相反,作為實參的時候是起到“解包”的作用。
一、星號(*)作為形參,表示調用可變參數函數:

通過在形參前加一個星號(*)或兩個星號(**)來指定函數可以接收任意數量的實參。
  1. def fun1(*args):       
  2.         print(type(args)) 
  3.         print(args)
  4.         
  5. fun1(1, 2, 3, 4, 5)
  6. # 输出:
  7. # <class 'tuple'>
  8. # (1, 2, 3, 4, 5)
  1. def fun2(**args):
  2.         print(type(args))
  3.         print(args)
  4.         
  5. fun2(a=1, b=2, c=3, d=4, e=5)
  6. # 输出:
  7. # <class 'dict'>
  8. # {'e': 5, 'a': 1, 'c': 3, 'd': 4, 'b': 2}
  • 從兩個示例的輸出可以看出:當參數形如*args 時,傳遞給函數的任意個實參會按位置打包成一個元組(tuple);
  • 當參數形如**args 時,傳遞給函數的任意個key = value 實參會被包裝進一個字典(dict)。
二、星號(*)作為實參時,表示通過解包參數調用函數

有打包就有解包,通過在實參前加一個星號(*)或兩個星號(**)來對列表(list)、元組(tuple)或字典(dict)進行解包:
  1. >>> a = [1, 2, 3, 4, 5]
  2. >>> b = (1, 2, 3, 4, 5)
  3. >>> fun1(*a)
  4. (1, 2, 3, 4, 5)
  5. >>> fun1(*b)
  6. (1, 2, 3, 4, 5)
  7. >>> c = {'one':1, 'two':2, 'three':3}
  8. >>> fun2(**c)
  9. {'two': 2, 'one': 1, 'three': 3}
  10. >>> 
總結:一個星號(*)用來打包和解包序列,兩個星號(**)用來打包和解包字典。


0 留言:

發佈留言