天天看點

tkinter: 基本+Button+Layout簡介ButtonLayout

簡介

簡介

  • Tcl
    • 動态解釋型程式設計語言
    • 可獨立執行,多嵌入C程式中作為腳本引擎,或者作為使用Tk工具包的接口
    • Tcl庫可以建立一個或多個Tcl解釋器執行個體,然後在這些執行個體上運作C或Tcl指令和腳本
    • 每個解釋器有一個事件隊列,接受事件并處理他們
  • Tk
    • 用C語言實作的一個Tcl包
    • 添加了自定義指令建立和操作GUI元件
    • 是唯一一個專門為進階動态語言(如 Python、 Tcl、 Ruby、 Perl 等)設計的跨平台(Windows、 Mac、 Unix)圖形使用者界面工具包
    • Tk的元件可以支援豐富的自定義,但風格比較過時
    • 使用Tcl的事件隊列生成和處理GUI事件
  • Ttk
    • 主體化Tk(Themed Tk)
    • 相比經典Tk,提供更新的Tk元件,提供更好的樣式
  • Tkinter是Python 的标準 Tk GUI 工具包的接口,可以實作簡單的跨平台GUI程式
  • Tkinter 是 Python 内置的标準 GUI 庫,無需額外安裝
  • Python2.x 版本使用的庫名為 Tkinter
  • Python3.x 版本使用的庫名為 tkinter

參考

Python GUI程式設計(Tkinter) 菜鳥教程

TkDocs

TkDocs Tutorial

TkDocs reference

Python interface to Tcl/Tk

Tk Commands

Button

Python2.x vs Python3.x

Python2.x Python3.x
Tkinter tkinter
ScrolledText tkinter.scrolledtext
ttk tkinter.ttk
tkMesageBox tkinter.messagebox
tkAxxBxx tkinter.axxbxx
  • 導入tkinter,處理下python2和python3的差異
  • 繼承Frame Class,初始化Frame,初始化其他參數
  • 擷取螢幕大小,設定App大小為螢幕大小的百分之80
  • 設定App标題
  • 以自身為master建立控件,配置控件,監聽處理控件事件
  • 放置控件,pack()或grid()或place()
  • 程式進入主循環,顯示程式mainloop()
tkinter: 基本+Button+Layout簡介ButtonLayout
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

if sys.version_info[0] < 3:
    import Tkinter as tk     ## Python 2.x
    import tkFont as tk_font
    import tkMessageBox as tk_messagebox
else:
    import tkinter as tk     ## Python 3.x
    import tkinter.font as tk_font
    import tkinter.messagebox as tk_messagebox


class App(tk.Frame):

	def __init__(self, master=None):

		tk.Frame.__init__(self, master)

		self.font = tk_font.Font(family='Helvetica', size=36, weight='bold')

		self.config(bg='black')

		self.setScreenSize()

		# self        = tk.Frame()
		# self.master = tk.Tk()
		self.master.title("ButtonTest")

		self.createWidgets()

	def setScreenSize(self):
		ratio = 0.8
		screen_h = self.master.winfo_screenheight()
		screen_w = self.master.winfo_screenwidth()

		# print(screen_h, screen_w)
		app_h = round(screen_h * ratio)
		app_w = round(screen_w * ratio)

		y = round(screen_h * (1 - ratio) / 2.0)
		x = round(screen_w * (1 - ratio) / 2.0)

		geometry = '' + str(app_w) + 'x' + str(app_h) + '+' + str(x) + '+' + str(y)
		# print(geometry)
		self.master.geometry(geometry)

	def createWidgets(self):

		self.button = tk.Button(self, text="hello", bg="red", fg="#0000FF", font=self.font, command=self.helloCallBack)

		self.draw()

	def helloCallBack(self):

		tk_messagebox.showinfo("Title", "Message")

	def draw(self):

		self.pack(padx=50, pady=50)

		self.button.pack(padx=50, pady=50)

		self.mainloop()

if __name__ == '__main__':

	App()

           

Layout

我們嘗試實作一個如下的布局來學習tkinter的布局

tkinter: 基本+Button+Layout簡介ButtonLayout

pack

pack CMD

anchor + side定位

  • anchor
    • 元件放在父元件的什麼位置,上下左右搭配8個方向,然後還有中間
    • s要搭配side=bottom,不然跟n效果一樣
  • side
    • 放在上一個元件的上下左右,比如left,就是放在上一個元件左邊
tkinter: 基本+Button+Layout簡介ButtonLayout
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import random

if sys.version_info[0] < 3:
    import Tkinter as tk     ## Python 2.x
    import tkMessageBox as tk_messagebox
else:
    import tkinter as tk     ## Python 3.x
    import tkinter.messagebox as tk_messagebox


class App(tk.Frame):

	def __init__(self, master=None):

		tk.Frame.__init__(self, master)

		self.master.title("pack")

		self.font = 'Times 20 bold'

		self.config(height=600, width=600)

		self.createWidgets()

	def createWidgets(self):

		self.createFrame1()
		self.createFrame2()
		self.createFrame3()
		self.draw()

	def createFrame1(self):
		frame = tk.Frame(self, height=200, width=800)
		self.createBtn(frame, anchor='NW')
		self.createBtn(frame, anchor='N')
		self.createBtn(frame, anchor='NE')
		frame.pack()
		frame.pack_propagate(0)

	def createFrame2(self):
		frame = tk.Frame(self, height=200, width=800)
		self.createBtn(frame, anchor='W', side='left')
		self.createBtn(frame, anchor='CENTER', side=None)
		self.createBtn(frame, anchor='E', side='right')
		frame.pack()
		frame.pack_propagate(0)

	def createFrame3(self):
		frame = tk.Frame(self, height=200, width=800)
		self.createBtn(frame, anchor='SW', side='bottom')
		self.createBtn(frame, anchor='S', side='bottom')
		self.createBtn(frame, anchor='SE', side='bottom')
		frame.pack(side='bottom')
		frame.pack_propagate(0)

	def createBtn(self, parent, anchor, side='top'):
		bg = self.getRandColor()
		frame = tk.Frame(parent, height=200, width=200, bg=bg)
		button = tk.Button(frame, text=anchor)
		frame.pack(side='left')
		frame.pack_propagate(0)
		if(anchor == 'CENTER'):
			button.pack(padx=50, pady=50, expand=True)
		else:
			button.pack(anchor=anchor.lower(), side=side)

	def getRandColor(self):
		return '#' + self.getRandRGB() + self.getRandRGB() + self.getRandRGB()

	def getRandRGB(self):
		return '{:02X}'.format(random.randint(0, 255))

	def helloCallBack(self):

		tk_messagebox.showinfo("Title", "Message")

	def draw(self):

		self.pack()
		self.pack_propagate(0)

		self.mainloop()

if __name__ == '__main__':

	App()

           

假設我隻想用一個Frame,就會顯得很奇怪

tkinter: 基本+Button+Layout簡介ButtonLayout
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import random

if sys.version_info[0] < 3:
    import Tkinter as tk     ## Python 2.x
    import tkMessageBox as tk_messagebox
else:
    import tkinter as tk     ## Python 3.x
    import tkinter.messagebox as tk_messagebox


class App(tk.Frame):

	def __init__(self, master=None):

		tk.Frame.__init__(self, master)

		self.master.title("pack")

		self.font = 'Times 20 bold'

		self.config(height=600, width=600)

		self.createWidgets()

	def createWidgets(self):

		self.createBtn(self, anchor='W', side='left')
		self.createBtn(self, anchor='NW', side='top')
		self.createBtn(self, anchor='N', side='top')
		self.createBtn(self, anchor='NE', side='top')
		self.createBtn(self, anchor='CENTER', side='bottom')
		self.createBtn(self, anchor='SW', side='bottom')
		self.createBtn(self, anchor='S', side='bottom')
		self.createBtn(self, anchor='SE', side='bottom')
		self.createBtn(self, anchor='E', side='right')
		self.draw()

	def createBtn(self, parent, anchor, side='top'):
		bg = self.getRandColor()
		button = tk.Button(parent, text=anchor, bg=self.getRandColor())
		if(anchor == 'CENTER'):
			button.pack(padx=50, pady=50, expand=True)
		else:
			button.pack(anchor=anchor.lower(), side=side)

	def getRandColor(self):
		return '#' + self.getRandRGB() + self.getRandRGB() + self.getRandRGB()

	def getRandRGB(self):
		return '{:02X}'.format(random.randint(0, 255))

	def helloCallBack(self):

		tk_messagebox.showinfo("Title", "Message")

	def draw(self):

		self.pack()
		self.pack_propagate(0)

		self.mainloop()

if __name__ == '__main__':

	App()

           

place

  • x,y
    • 絕對定位
  • relx,rely
    • 相對定義,relx=0就是最左,relx=1就是最右
tkinter: 基本+Button+Layout簡介ButtonLayout
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import random

if sys.version_info[0] < 3:
    import Tkinter as tk     ## Python 2.x
    import tkMessageBox as tk_messagebox
else:
    import tkinter as tk     ## Python 3.x
    import tkinter.messagebox as tk_messagebox


class App(tk.Frame):

	def __init__(self, master=None):

		tk.Frame.__init__(self, master)

		self.master.title("pack")

		self.font = 'Times 20 bold'

		self.config(height=600, width=600)

		self.createWidgets()

	def createWidgets(self):

		self.createBtn(0, 0, 'nw')
		self.createBtn(0.5, 0, 'n')
		self.createBtn(1, 0, 'ne')

		self.createBtn(0, 0.5, 'w')
		self.createBtn(0.5, 0.5, 'center')
		self.createBtn(1, 0.5, 'e')

		self.createBtn(0, 1, 'sw')
		self.createBtn(0.5, 1, 's')
		self.createBtn(1, 1, 'se')
		
		self.draw()

	def createBtn(self, x, y, anchor):
		button = tk.Button(self, text='(' + str(x) + ', ' + str(y) + ')', bg=self.getRandColor())
		button.place(relx=x, rely=y, anchor=anchor)

	def getRandColor(self):
		return '#' + self.getRandRGB() + self.getRandRGB() + self.getRandRGB()

	def getRandRGB(self):
		return '{:02X}'.format(random.randint(0, 255))


	def draw(self):

		self.pack()
		self.pack_propagate(0)

		self.mainloop()

if __name__ == '__main__':

	App()

           

grid

這個就是css中的table,比較簡單了

  • row,rowspan
  • column,columnspan
  • sticky
    • 元件大小小于父元件時怎麼填充父元件
    • nesw:水準垂直都拉伸填充
    • ns:垂直填充
    • ew:水準填充
tkinter: 基本+Button+Layout簡介ButtonLayout
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import random

if sys.version_info[0] < 3:
    import Tkinter as tk     ## Python 2.x
    import tkMessageBox as tk_messagebox
else:
    import tkinter as tk     ## Python 3.x
    import tkinter.messagebox as tk_messagebox


class App(tk.Frame):

	def __init__(self, master=None):

		tk.Frame.__init__(self, master)

		self.master.title("pack")

		self.font = 'Times 20 bold'

		# self.config(height=600, width=600)

		self.createWidgets()

	def createWidgets(self):

		self.createBtn(0, 0, 1, 2)
		self.createBtn(0, 2, 2, 1)

		self.createBtn(1, 0, 2, 1)
		self.createBtn(1, 1)

		self.createBtn(2, 1, 1, 2)
		
		self.draw()

	def createBtn(self, row, col, rowspan = 1, colspan = 1):
		button = tk.Button(self, text='(' + str(row) + ', ' + str(col) + ')', bg=self.getRandColor(), width=20, height=8)
		button.grid(row=row, column=col, rowspan=rowspan, columnspan=colspan, sticky="nesw")

	def getRandColor(self):
		return '#' + self.getRandRGB() + self.getRandRGB() + self.getRandRGB()

	def getRandRGB(self):
		return '{:02X}'.format(random.randint(0, 255))


	def draw(self):

		self.pack()
		self.pack_propagate(0)

		self.mainloop()

if __name__ == '__main__':

	App()