分享

Python GUI进阶(ttk)

 和相品 2019-07-16

Python3.5版GUI官方文档:https://docs./3.5/library/tk.html

上一篇介绍的GUI界面有以下两个较大的缺点:

1、界面比较丑陋,控件种类有限。

2、界面布局逻辑性差。

针对以上两个缺点,引入Tkinter 中的ttk组件。

需要说明的,ttk的很多组件同Tkinter都是相同的,在这种情况下,ttk将覆盖Tkinter的组件,将采用ttk的特性。--原文如下

And then severalttk widgets (Button, Checkbutton, Entry, Frame, Label, LabelFrame, Menubutton,PanedWindow, Radiobutton, Scale and Scrollbar) will automatically substitutefor the Tk widgets.

使用ttk以后的组件,同windows操作系统(这里是win7系统)的外观的一致性更高,看起来也会舒服很多。

需要注意的是:

ttk的用法同Tkinter还是相同的,但是有一些属性ttk不再支持,如 Tkinter 中的fg,bg 在ttk中以不被支持,它是通过style这个对象进行支持的,其它的方面还是变化不大。

下面的例子来源于《Python GUI Programming Cookbook》,自己在原来的基础上进行了一些改变,并添加了一些注释。界面图和源代码如下所示。

三个主页面的截图如下:

     


各种类型的对话框形式如下:

      

       

程序源代码如下:

  1. #======================
  2. # imports
  3. #======================
  4. import tkinter as tk
  5. from tkinter import ttk
  6. from tkinter import scrolledtext
  7. from tkinter import Menu
  8. from tkinter import Spinbox
  9. from tkinter import messagebox as mBox
  10. #由于tkinter中没有ToolTip功能,所以自定义这个功能如下
  11. class ToolTip(object):
  12. def __init__(self, widget):
  13. self.widget = widget
  14. self.tipwindow = None
  15. self.id = None
  16. self.x = self.y = 0
  17. def showtip(self, text):
  18. "Display text in tooltip window"
  19. self.text = text
  20. if self.tipwindow or not self.text:
  21. return
  22. x, y, _cx, cy = self.widget.bbox("insert")
  23. x = x + self.widget.winfo_rootx() + 27
  24. y = y + cy + self.widget.winfo_rooty() +27
  25. self.tipwindow = tw = tk.Toplevel(self.widget)
  26. tw.wm_overrideredirect(1)
  27. tw.wm_geometry("+%d+%d" % (x, y))
  28. label = tk.Label(tw, text=self.text, justify=tk.LEFT,
  29. background="#ffffe0", relief=tk.SOLID, borderwidth=1,
  30. font=("tahoma", "8", "normal"))
  31. label.pack(ipadx=1)
  32. def hidetip(self):
  33. tw = self.tipwindow
  34. self.tipwindow = None
  35. if tw:
  36. tw.destroy()
  37. #===================================================================
  38. def createToolTip( widget, text):
  39. toolTip = ToolTip(widget)
  40. def enter(event):
  41. toolTip.showtip(text)
  42. def leave(event):
  43. toolTip.hidetip()
  44. widget.bind('<Enter>', enter)
  45. widget.bind('<Leave>', leave)
  46. # Create instance
  47. win = tk.Tk()
  48. # Add a title
  49. win.title("Python 图形用户界面")
  50. # Disable resizing the GUI
  51. win.resizable(0,0)
  52. # Tab Control introduced here --------------------------------------
  53. tabControl = ttk.Notebook(win) # Create Tab Control
  54. tab1 = ttk.Frame(tabControl) # Create a tab
  55. tabControl.add(tab1, text='第一页') # Add the tab
  56. tab2 = ttk.Frame(tabControl) # Add a second tab
  57. tabControl.add(tab2, text='第二页') # Make second tab visible
  58. tab3 = ttk.Frame(tabControl) # Add a third tab
  59. tabControl.add(tab3, text='第三页') # Make second tab visible
  60. tabControl.pack(expand=1, fill="both") # Pack to make visible
  61. # ~ Tab Control introduced here -----------------------------------------
  62. #---------------Tab1控件介绍------------------#
  63. # We are creating a container tab3 to hold all other widgets
  64. monty = ttk.LabelFrame(tab1, text='控件示范区1')
  65. monty.grid(column=0, row=0, padx=8, pady=4)
  66. # Modified Button Click Function
  67. def clickMe():
  68. action.configure(text='Hello\n ' + name.get())
  69. action.configure(state='disabled') # Disable the Button Widget
  70. # Changing our Label
  71. ttk.Label(monty, text="输入文字:").grid(column=0, row=0, sticky='W')
  72. # Adding a Textbox Entry widget
  73. name = tk.StringVar()
  74. nameEntered = ttk.Entry(monty, width=12, textvariable=name)
  75. nameEntered.grid(column=0, row=1, sticky='W')
  76. # Adding a Button
  77. action = ttk.Button(monty,text="点击之后\n按钮失效",width=10,command=clickMe)
  78. action.grid(column=2,row=1,rowspan=2,ipady=7)
  79. ttk.Label(monty, text="请选择一本书:").grid(column=1, row=0,sticky='W')
  80. # Adding a Combobox
  81. book = tk.StringVar()
  82. bookChosen = ttk.Combobox(monty, width=12, textvariable=book)
  83. bookChosen['values'] = ('平凡的世界', '亲爱的安德烈','看见','白夜行')
  84. bookChosen.grid(column=1, row=1)
  85. bookChosen.current(0) #设置初始显示值,值为元组['values']的下标
  86. bookChosen.config(state='readonly') #设为只读模式
  87. # Spinbox callback
  88. def _spin():
  89. value = spin.get()
  90. #print(value)
  91. scr.insert(tk.INSERT, value + '\n')
  92. def _spin2():
  93. value = spin2.get()
  94. #print(value)
  95. scr.insert(tk.INSERT, value + '\n')
  96. # Adding 2 Spinbox widget using a set of values
  97. spin = Spinbox(monty, from_=10,to=25, width=5, bd=8, command=_spin)
  98. spin.grid(column=0, row=2)
  99. spin2 = Spinbox(monty, values=('Python3入门', 'C语言','C++', 'Java', 'OpenCV'), width=13, bd=3, command=_spin2)
  100. spin2.grid(column=1, row=2,sticky='W')
  101. # Using a scrolled Text control
  102. scrolW = 30; scrolH = 5
  103. scr = scrolledtext.ScrolledText(monty, width=scrolW, height=scrolH, wrap=tk.WORD)
  104. scr.grid(column=0, row=3, sticky='WE', columnspan=3)
  105. # Add Tooltip
  106. createToolTip(spin, '这是一个Spinbox.')
  107. createToolTip(spin2, '这是一个Spinbox.')
  108. createToolTip(action, '这是一个Button.')
  109. createToolTip(nameEntered,'这是一个Entry.')
  110. createToolTip(bookChosen, '这是一个Combobox.')
  111. createToolTip(scr, '这是一个ScrolledText.')
  112. # 一次性控制各控件之间的距离
  113. for child in monty.winfo_children():
  114. child.grid_configure(padx=3,pady=1)
  115. # 单独控制个别控件之间的距离
  116. action.grid(column=2,row=1,rowspan=2,padx=6)
  117. #---------------Tab1控件介绍------------------#
  118. #---------------Tab2控件介绍------------------#
  119. # We are creating a container tab3 to hold all other widgets -- Tab2
  120. monty2 = ttk.LabelFrame(tab2, text='控件示范区2')
  121. monty2.grid(column=0, row=0, padx=8, pady=4)
  122. # Creating three checkbuttons
  123. chVarDis = tk.IntVar()
  124. check1 = tk.Checkbutton(monty2, text="失效选项", variable=chVarDis, state='disabled')
  125. check1.select()
  126. check1.grid(column=0, row=0, sticky=tk.W)
  127. chVarUn = tk.IntVar()
  128. check2 = tk.Checkbutton(monty2, text="遵从内心", variable=chVarUn)
  129. check2.deselect() #Clears (turns off) the checkbutton.
  130. check2.grid(column=1, row=0, sticky=tk.W )
  131. chVarEn = tk.IntVar()
  132. check3 = tk.Checkbutton(monty2, text="屈于现实", variable=chVarEn)
  133. check3.deselect()
  134. check3.grid(column=2, row=0, sticky=tk.W)
  135. # GUI Callback function
  136. def checkCallback(*ignoredArgs):
  137. # only enable one checkbutton
  138. if chVarUn.get(): check3.configure(state='disabled')
  139. else: check3.configure(state='normal')
  140. if chVarEn.get(): check2.configure(state='disabled')
  141. else: check2.configure(state='normal')
  142. # trace the state of the two checkbuttons #??
  143. chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback())
  144. chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback())
  145. # Radiobutton list
  146. values = ["富强民主", "文明和谐", "自由平等","公正法治","爱国敬业","诚信友善"]
  147. # Radiobutton callback function
  148. def radCall():
  149. radSel=radVar.get()
  150. if radSel == 0: monty2.configure(text='富强民主')
  151. elif radSel == 1: monty2.configure(text='文明和谐')
  152. elif radSel == 2: monty2.configure(text='自由平等')
  153. elif radSel == 3: monty2.configure(text='公正法治')
  154. elif radSel == 4: monty2.configure(text='爱国敬业')
  155. elif radSel == 5: monty2.configure(text='诚信友善')
  156. # create three Radiobuttons using one variable
  157. radVar = tk.IntVar()
  158. # Selecting a non-existing index value for radVar
  159. radVar.set(99)
  160. # Creating all three Radiobutton widgets within one loop
  161. for col in range(4):
  162. #curRad = 'rad' + str(col)
  163. curRad = tk.Radiobutton(monty2, text=values[col], variable=radVar, value=col, command=radCall)
  164. curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3)
  165. for col in range(4,6):
  166. #curRad = 'rad' + str(col)
  167. curRad = tk.Radiobutton(monty2, text=values[col], variable=radVar, value=col, command=radCall)
  168. curRad.grid(column=col-4, row=7, sticky=tk.W, columnspan=3)
  169. style = ttk.Style()
  170. style.configure("BW.TLabel", font=("Times", "10",'bold'))
  171. ttk.Label(monty2, text=" 社会主义核心价值观",style="BW.TLabel").grid(column=2, row=7,columnspan=2, sticky=tk.EW)
  172. # Create a container to hold labels
  173. labelsFrame = ttk.LabelFrame(monty2, text=' 嵌套区域 ')
  174. labelsFrame.grid(column=0, row=8,columnspan=4)
  175. # Place labels into the container element - vertically
  176. ttk.Label(labelsFrame, text="你才25岁,你可以成为任何你想成为的人。").grid(column=0, row=0)
  177. ttk.Label(labelsFrame, text="不要在乎一城一池的得失,要执着。").grid(column=0, row=1,sticky=tk.W)
  178. # Add some space around each label
  179. for child in labelsFrame.winfo_children():
  180. child.grid_configure(padx=8,pady=4)
  181. #---------------Tab2控件介绍------------------#
  182. #---------------Tab3控件介绍------------------#
  183. tab3 = tk.Frame(tab3, bg='#AFEEEE')
  184. tab3.pack()
  185. for i in range(2):
  186. canvas = 'canvas' + str(col)
  187. canvas = tk.Canvas(tab3, width=162, height=95, highlightthickness=0, bg='#FFFF00')
  188. canvas.grid(row=i, column=i)
  189. #---------------Tab3控件介绍------------------#
  190. #----------------菜单栏介绍-------------------#
  191. # Exit GUI cleanly
  192. def _quit():
  193. win.quit()
  194. win.destroy()
  195. exit()
  196. # Creating a Menu Bar
  197. menuBar = Menu(win)
  198. win.config(menu=menuBar)
  199. # Add menu items
  200. fileMenu = Menu(menuBar, tearoff=0)
  201. fileMenu.add_command(label="新建")
  202. fileMenu.add_separator()
  203. fileMenu.add_command(label="退出", command=_quit)
  204. menuBar.add_cascade(label="文件", menu=fileMenu)
  205. # Display a Message Box
  206. def _msgBox1():
  207. mBox.showinfo('Python Message Info Box', '通知:程序运行正常!')
  208. def _msgBox2():
  209. mBox.showwarning('Python Message Warning Box', '警告:程序出现错误,请检查!')
  210. def _msgBox3():
  211. mBox.showwarning('Python Message Error Box', '错误:程序出现严重错误,请退出!')
  212. def _msgBox4():
  213. answer = mBox.askyesno("Python Message Dual Choice Box", "你喜欢这篇文章吗?\n您的选择是:")
  214. if answer == True:
  215. mBox.showinfo('显示选择结果', '您选择了“是”,谢谢参与!')
  216. else:
  217. mBox.showinfo('显示选择结果', '您选择了“否”,谢谢参与!')
  218. # Add another Menu to the Menu Bar and an item
  219. msgMenu = Menu(menuBar, tearoff=0)
  220. msgMenu.add_command(label="通知 Box", command=_msgBox1)
  221. msgMenu.add_command(label="警告 Box", command=_msgBox2)
  222. msgMenu.add_command(label="错误 Box", command=_msgBox3)
  223. msgMenu.add_separator()
  224. msgMenu.add_command(label="判断对话框", command=_msgBox4)
  225. menuBar.add_cascade(label="消息框", menu=msgMenu)
  226. #----------------菜单栏介绍-------------------#
  227. # Change the main windows icon
  228. win.iconbitmap(r'C:\Users\feng\Desktop\研.ico')
  229. # Place cursor into name Entry
  230. nameEntered.focus()
  231. #======================
  232. # Start GUI
  233. #======================
  234. win.mainloop()


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约