• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 【Tkinter】Python標準庫中的GUI框架入門之一——window和widget

    標簽: python語言  python  tkinter

    本博客高度參考了這篇文章,可以認為是該文章的譯文,將分期發表。
    對原作者和網站提供如此高質量的教程表示感謝!

    圖形用戶界面(Graphical User Interface,簡稱GUI),是指采用圖形方式顯示計算機的操作界面。相較于命令行,這種方式上手難度低,更加容易為普通用戶所接受。

    Python中有許多GUI框架,但Tkinter是唯一一種被寫入標準庫中的。Tkinter是跨平臺(cross-platform)的,這意味著相同的代碼可以在Windows、Linux和macOS上運行,而且GUI中的可視化元素(按鈕、文本框等)可以根據其所在的操作系統進行自動渲染。

    當然,Tkinter也有其不足之處。其中一點就是,它顯得“過時”了——許多可視化元素的樣式看起來像上個世紀的個人電腦中的一樣。如果你追求新潮、酷炫,那么Tkinter多半沒法滿足你的要求;如果只是想實現某些功能而不怎么注重外觀,那么輕量級的Tkinter足以讓你快速、便捷地構建自己的應用。

    1. 窗口(window)

    在一個GUI中,最基礎最底層的元素是窗口(window)。如果一個把一個完整的GUI比作一幅畫,那么window就是畫布,所有的操作都在這張畫布上進行。所以,在編寫GUI之前,需要創建這樣一張畫布——用編程的語言來說,就是要先實例化這樣一個window。

    首先,打開Python的交互式窗口,導入tkinter(在所有的交互代碼中,均省略了’>>>’):

    import tkinter as tk
    

    然后,實例化一個window

    window = tk.Tk()
    

    這時,操作系統就會彈出一個新的窗口,大概長這個樣子:
    在這里插入圖片描述
    至此,畫布就準備好了,因為現在什么都沒做,所以畫布是空白的。我們可以向這張畫布上寫一些字符:

    greeting = tk.Label(text='Hello Tkinter!')
    greeting.pack()
    

    最終彈窗的結果是這樣的:
    在這里插入圖片描述
    第一行代碼的意思是,實例化一個Label,在實例化的過程中,通過text指定了該變量要顯示的內容。

    第二行代碼的意思是,將該實例固定到畫布上。

    LabelTkinter中的一個類,單詞翻譯成中文的意思是“說明性短語”,在GUI領域,這個類被叫做“控件”(widget),通過向窗口中添加不同的控件,并對它們進行組合,就形成了各式各樣的GUI了。

    Windows操作系統之所以這樣命名,就是因為它本質上就是許多window的組合,當然這些組合是非常復雜的。這些window為用戶屏蔽了看上去很枯燥的命令操作,從而提升了用戶體驗,但代價也是很巨大的,就是速度變慢。這種變慢對于普通用戶來說可能并沒有什么感覺,但是對于服務器而言,卻很可能是致命的,這也是為什么絕大部分服務器都采用沒有GUI的Linux操作系統的原因之一。

    2. 控件(widget)

    如果說窗口是畫布,那么控件就是不同的顏料了。它們也是組成一個GUI所必不可少的東西,是用戶與程序進行交互的基礎。在Tkinter中,每一種控件都由一個類來定義,一些常見的控件及其說明如下:

    控件 說明
    Label 用于在屏幕上打印文本
    Button 按鈕,可以包含文字,并在單擊時進行相應的操作
    Entry 只允許單行文本輸入的控件
    Text 允許多行文本輸入的控件
    Frame 一個矩形區域,用于對控件分組或為其提供填充

    當然,還有許多其他的控件,但上面這些確實是最基礎的,熟練使用這些控件,就可以開發一些有趣的東西,并對Tkinter的運用有相當程度的理解。

    2.1 使用Label控件

    Label控件可以用來展示文本或者圖片。這些文本(圖片)是不能夠被用戶編輯的,上面你已經看到了一個展示文本的例子,而實際上我們還可以對展示的文本進行更多的操作:

    greeting = tk.Label(
        text='Hello Tkinter!',
        foreground="white",
        background="black"
    	)
    greeting.pack()
    

    很直觀,我們改變了前景色和背景色,彈窗如下:
    在這里插入圖片描述
    關于顏色,可以查看顏色手冊。當然也可以使用十六進制的RGB顏色值,這更加靈活。

    Tkinter還提供了縮寫,如果你覺得background這個單詞太長了,可以用簡寫bg代替它,同理,可以用fg代替foreground

    通過指定寬度和高度,來控制控件的大小:

    greeting = tk.Label(
        text='Hello Tkinter!',
        fg="white",
        bg="black",
        width=10,
        height=10
    	)
    greeting.pack()
    

    窗口如下:
    在這里插入圖片描述
    這里就存在一個問題了:寬度和高度都指定的是“10”,怎么渲染出來的不是一個正方形呢?這是因為在Tkinter中,寬度和高度都是以文本單元(text unit)來度量的。具體來說,1單位的寬度由系統中的字符“0”或者數字0的寬度來決定,1單位的高度由系統中的字符“0”或者數字0的高度來決定。

    采用這種設置而不是用英寸、厘米、像素等度量,也是為了保證程序在跨平臺運行時顯示一致。以字符來度量意味著控件大小與用戶機器上的默認字體是相關的,這樣就保證了文本能夠正確地嵌入到Label和Button中。

    2.2 使用Button控件

    顧名思義,Button控件就是用來展示一個按鈕的,點擊該按鈕,可以實現一個操作。

    事實上,我們可以將Button理解為一個可以點擊的Label。用于創建Label的關鍵字參數也適用于Button控件:

    button = tk.Button(
        text="Click me!",
        width=25,
        height=5,
        bg="blue",
        fg="yellow",
    )
    

    彈窗是這樣的:
    在這里插入圖片描述

    2.3 使用Entry控件

    當你需要收集用戶輸入的一些信息,比如用戶名、密碼等,這時候就可以使用Entry控件了。它顯示為一個小的文本框,用戶可以在其中輸入一些文本。創建和設計Entry控件的工作原理與上面提到的LabelButton非常類似:

    entry = tk.Entry(fg="yellow", bg="blue", width=50)
    

    彈窗如下:
    在這里插入圖片描述
    上面已經說過,Entry是一個單行輸入的文本框,那么一個重要的功能就是如何使用它從用戶那里獲取信息。對于一個Entry實例,最常用的方法有三個:

    • .get():獲取Entry實例中的文本
    • .delete():刪除Entry實例中的文本
    • .insert():向Entry實例中插入文本

    下面通過具體的例子來演示這些方法的作用。

    首先,創建一個GUI,其窗口顯示的內容如下:
    在這里插入圖片描述
    生成這個窗口的腳本為:

    import tkinter as tk
    
    
    window = tk.Tk()
    label = tk.Label(text='name')
    entry = tk.Entry()
    label.pack()
    entry.pack()
    

    需要注意的一點是,兩個控件都是居中對齊的,這也是.pack()方法的特性之一,后文會對這個特性進行說明。

    單擊一下輸入框,就可以在里面輸入內容了,假設我們輸入“Real Python”。為了驗證各個方法的作用,我們在交互式窗口接著輸入:

    entry.get()
    

    則會打印出“Real Python”的字符。

    .delete()方法用于刪除字符,其使用與對待Python中的字符串的使用方式很相似,需要傳入一個參數告訴Python刪除的字符的位置:

    entry.delete(0)
    

    即刪除了第一個字符,這時彈窗為:
    在這里插入圖片描述
    如果想一次性刪除好幾個字符,還需要傳入第二個整數,用于告訴Python刪除字符的終止位置:

    entry.delete(0, 4)
    

    這時,彈窗為:
    在這里插入圖片描述
    第二個數字為終止字符的位置,該位置的字符不會被刪除,上面的代碼實際上只刪除了位置為0、1、2、3的字符。

    如果想一次性刪除全部,可以用如下的方法實現:

    entry.delete(0, tk.END)
    

    這時,彈窗里面的Entry控件又為空了:
    在這里插入圖片描述
    與之相反,你可以通過.insert()方法來向控件中添加字符:

    entry.insert(0, "Python")
    

    第一個整數告訴Python從哪里開始插入字符。如果Entry控件中沒有任何字符,那么新字符總是插入到控件的開始位置上,與你傳入的第一個參數無關。

    這時的窗口又變成了這樣:
    在這里插入圖片描述
    再繼續往里面插值:

    entry.insert(0, "Real ")
    

    會發現,窗口變成了第一次輸入后的樣子:
    在這里插入圖片描述

    2.4 使用Text控件

    可以將Text控件理解為一個可以輸入很多行文本的Entry。事實上,它的作用就是如此。

    Entry控件類似,Text控件也有三種主要的方法:

    • .get():獲取Text實例中的文本
    • .delete():刪除Text實例中的文本
    • .insert():向Text實例中插入文本

    需要注意的是,盡管方法名稱完全一致,但由于多行文本的原因,其使用方法略有不同。

    首先,我們重新創建一個帶Text控件的GUI:

    window = tk.Tk()
    text_box = tk.Text()
    text_box.pack()
    

    GUI應該具有如下樣式:

    在這里插入圖片描述

    單擊該Text中的任意位置,然后就可以輸入字符了,這里我輸入了“Hello World”,占用了兩行。

    Entry控件相類似,可以采用.get()方法來提取Text控件中的內容。但需要注意的是,Text控件的.get()方法至少需要一個參數。如果只傳入一個參數,那么你將得到該位置上的字符;如果想要得到數個字符,則需要傳入開始位置參數和終止位置參數。由于Text控件中的內容可能包含多行,因此,每個參數都必須包含兩部分內容:字符的行號字符在該行中的位置

    所以,位置參數的格式是<line>.<char>。為了直觀的理解,嘗試一下下面的代碼:

    text_box.get("1.0")
    # 'H'
    
    text_box.get("1.0", "1.5")
    # 'Hello'
    
    text_box.get("1.0", tk.END)
    # 'Hello\nWorld\n'
    

    注意到,換行符也是一個字符。

    在理解了.get()方法之后,相應的.delete()方法和.insert()方法也是通過類似的方式進行調用的。具體不再贅述,只需要記住,\n也是一個字符。

    2.5 使用Frame控件

    一個好的GUI不但有很多控件,它們之間還得通過合適的方式組合起來才行,Frame控件就可以滿足這個要求。

    可以把Frame控件理解為其他控件的容器,在實例化其他控件時,通過master參數來指定該控件屬于哪個Frame。具體的,看以下代碼:

    import tkinter as tk
    
    window = tk.Tk()
    
    frame_a = tk.Frame()
    frame_b = tk.Frame()
    
    label_a = tk.Label(master=frame_a, text="I'm in Frame A")
    label_a.pack()
    
    label_b = tk.Label(master=frame_b, text="I'm in Frame B")
    label_b.pack()
    
    frame_a.pack()
    frame_b.pack()
    

    彈窗如下:
    在這里插入圖片描述
    代碼的理解也是比較直觀的:

    • 5、6行實例化了兩個Frame控件;
    • 8、9行實例化了一個Label控件,并通過master參數,指定了該控件包含于frame_a中;
    • 11、12行操作類似;
    • 14、15行將兩個Frame控件pack到window上;
    • 17行啟動了window的主循環,以保證窗口處于打開狀態。

    接下來,如果我改變14和15行的順序,那么彈窗是什么樣的呢?

    ...
    frame_b.pack()
    frame_a.pack()
    ...
    

    彈窗如下:
    在這里插入圖片描述
    通過前后兩次實驗的對比,可以這樣理解Frame控件的工作原理:其他控件在實例化時,通過master參數指定了其所屬的Frame,然后將其pack到該Frame上。最后,將Frame實例pack到主window上,就顯示出來各個控件了。

    版權聲明:本文為SunJW_2017原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/SunJW_2017/article/details/105927570

    智能推薦

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    猜你喜歡

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    19.vue中封裝echarts組件

    19.vue中封裝echarts組件 1.效果圖 2.echarts組件 3.使用組件 按照組件格式整理好數據格式 傳入組件 home.vue 4.接口返回數據格式...

    劍指Offer39-調整數組順序使奇數位于偶數前面

    一開始想著用冒泡排序的方法來做,但是bug還是很多,后來看了評論區答案,發現直接空間換時間是最簡單的,而且和快排的寫法是類似的。...

    【一只蒟蒻的刷題歷程】【藍橋杯】歷屆試題 九宮重排 (八數碼問題:BFS+集合set)

    資源限制 時間限制:1.0s 內存限制:256.0MB 問題描述 如下面第一個圖的九宮格中,放著 1~8 的數字卡片,還有一個格子空著。與空格子相鄰的格子中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。 我們把第一個圖的局面記為:12345678. 把第二個圖的局面記為:123.46758 顯然是按從上到下,從左到右的順序記錄數字,空格記為句點。 本題目的任務是已知九宮的初態...

    精品国产乱码久久久久久蜜桃不卡