Tkinter框架的高度和宽度与主窗口的完整尺寸不匹配。

huangapple go评论118阅读模式
英文:

Tkinter frames height and width not matching the full size of the main window

问题

  1. import tkinter
  2. class MainBox:
  3. def __init__(self):
  4. # 主窗口规格
  5. self.root = tkinter.Tk()
  6. self.root.title('实用工具箱')
  7. self.root.geometry('700x450')
  8. self.root.resizable(False, False)
  9. self.root.configure(bg='red')
  10. self.root.iconbitmap(r'D:\2xProjects\Python\UtilityBox\resources\appicon.ico')
  11. self.window_already_open = False
  12. # 操作框架(搜索、排序、删除、重命名等)
  13. self.operations_frame = tkinter.Frame(self.root, width=700, height=350, bg='#293556')
  14. self.operations_frame.grid(row=0, sticky='ew')
  15. # 日志框架
  16. # 用于记录操作结果(成功或失败)
  17. # 例如:搜索:在指定路径中找到文件/文件
  18. self.log_frame = tkinter.Frame(self.root, width=700, height=100, bg='#2E4583')
  19. self.log_frame.grid(row=1, sticky='ew')
  20. # 用户必须填写操作所需的搜索窗口
  21. def search_details():
  22. if not self.window_already_open:
  23. self.window_already_open = True
  24. search_window = tkinter.Toplevel()
  25. search_window.title('搜索选项')
  26. search_window.geometry('250x160')
  27. search_window.resizable(False, False)
  28. search_window.configure(bg='#293556')
  29. file_path = tkinter.Label(search_window, width=35, wraplength=150)
  30. file_path.grid(row=0, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
  31. # 基于文件名搜索(例如:名称或名称.扩展)
  32. file_name = tkinter.Label(search_window, width=35, wraplength=150)
  33. file_name.grid(row=1, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
  34. # 搜索具有关联扩展名的文件(例如:所有.txt文件)
  35. extension = tkinter.Label(search_window, width=35, wraplength=150)
  36. extension.grid(row=2, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
  37. start_searching = tkinter.Button(search_window, text='开始搜索', bg='#294F63', fg='white')
  38. start_searching.grid(row=4, column=0, sticky='nw', padx=15, pady=(15, 0))
  39. def on_window_close():
  40. self.window_already_open = False
  41. search_window.destroy()
  42. search_window.protocol("WM_DELETE_WINDOW", on_window_close)
  43. # 搜索功能(按钮和功能描述)
  44. search_option = tkinter.Button(self.operations_frame, text='搜索', bg='#294F63', fg='white',
  45. command=search_details)
  46. search_option.grid(row=0, column=0, sticky='nw', padx=15, pady=(15, 0))
  47. search_description = tkinter.Label(self.operations_frame,
  48. text='搜索描述')
  49. search_description.grid(row=0, column=0, sticky='nw', padx=70, pady=(18, 0))
  50. # 排序功能(按钮和功能描述)
  51. sort_option = tkinter.Button(self.operations_frame, text='排序', bg='#294F63', fg='white')
  52. sort_option.grid(row=1, column=0, sticky='nw', padx=15, pady=(5, 0))
  53. sort_description = tkinter.Label(self.operations_frame,
  54. text='排序描述')
  55. sort_description.grid(row=1, column=0, sticky='nw', padx=55, pady=(7, 0))
  56. # 删除功能(按钮和功能描述)
  57. delete_option = tkinter.Button(self.operations_frame, text='删除', bg='#294F63', fg='white')
  58. delete_option.grid(row=2, column=0, sticky='nw', padx=15, pady=(5, 0))
  59. delete_description = tkinter.Label(self.operations_frame,
  60. text='删除描述')
  61. delete_description.grid(row=2, column=0, sticky='nw', padx=105, pady=(7, 0))
  62. # 重命名功能(按钮和功能描述)
  63. rename_option = tkinter.Button(self.operations_frame, text='重命名', bg='#294F63', fg='white')
  64. rename_option.grid(row=3, column=0, sticky='nw', padx=15, pady=(5, 0))
  65. rename_description = tkinter.Label(self.operations_frame,
  66. text='重命名描述')
  67. rename_description.grid(row=3, column=0, sticky='nw', padx=105, pady=(7, 0))
  68. # 复制功能(按钮和功能描述)
  69. duplication_option = tkinter.Button(self.operations_frame, text='复制', bg='#294F63', fg='white')
  70. duplication_option.grid(row=4, column=0, sticky='nw', padx=15, pady=(5, 0))
  71. duplication_description = tkinter.Label(self.operations_frame,
  72. text='复制描述')
  73. duplication_description.grid(row=4, column=0, sticky='nw', padx=105, pady=(7, 0))
  74. # 权限功能(按钮和功能描述)
  75. permissions_option = tkinter.Button(self.operations_frame, text='权限', bg='#294F63', fg='white')
  76. permissions_option.grid(row=5, column=0, sticky='nw', padx=15, pady=(5, 0))
  77. permissions_description = tkinter.Label(self.operations_frame,
  78. text='权限描述')
  79. permissions_description.grid(row=5, column=0, sticky='nw', padx=105, pady=(7, 0))
  80. # 比较功能(按钮和功能描述)
  81. compare_option = tkinter.Button(self.operations_frame, text='比较', bg='#294F63', fg='white')
  82. compare_option.grid(row=6, column=0, sticky='nw', padx=15, pady=(5, 0))
  83. compare_description = tkinter.Label(self.operations_frame,
  84. text='比较描述')
  85. compare_description.grid(row=6, column=0, sticky='nw', padx=105, pady=(7, 0))
  86. # 预览功能(按钮和功能描述)
  87. preview_option = tkinter.Button(self.operations_frame, text='预览', bg='#294F63', fg='white')
  88. preview_option.grid(row=7, column=0, sticky='nw', padx=15, pady=(5, 0))
  89. preview_description = tkinter.Label(self.operations_frame,
  90. text='预览描述')
  91. preview_description.grid(row=7, column=0, sticky='nw', padx=105, pady=(7, 0))
  92. # 压缩/解压功能(按钮和功能描述)
  93. compression_decompression_option = tkinter.Button(self.operations_frame, text='压缩/解压',
  94. bg='#294F63', fg='white')
  95. compression_decompression_option.grid(row=8, column=0, sticky='nw', padx=15, pady=(5, 0))
  96. <details>
  97. <summary>英文:</summary>
  98. import tkinter
  99. class MainBox:
  100. def __init__(self):
  101. # Main windows specifications
  102. self.root = tkinter.Tk()
  103. self.root.title(&#39; Utility Box&#39;)
  104. self.root.geometry(&#39;700x450&#39;)
  105. self.root.resizable(False, False)
  106. self.root.configure(bg=&#39;red&#39;)
  107. self.root.iconbitmap(r&#39;D:\2xProjects\Python\UtilityBox\resources\appicon.ico&#39;)
  108. self.window_already_open = False
  109. # Operations frame (search, sort, delete, rename etc)
  110. self.operations_frame = tkinter.Frame(self.root, width=700, height=350, bg=&#39;#293556&#39;)
  111. self.operations_frame.grid(row=0, sticky=&#39;ew&#39;)
  112. # Log frame
  113. # Will log the results of the operations (either success or failure)
  114. # Ex search: found the file/ files in the specified path
  115. self.log_frame = tkinter.Frame(self.root, width=700, height=100, bg=&#39;#2E4583&#39;)
  116. self.log_frame.grid(row=1, sticky=&#39;ew&#39;)
  117. # Search window where user must fill the details required for the operation to start
  118. def search_details():
  119. if not self.window_already_open:
  120. self.window_already_open = True
  121. search_window = tkinter.Toplevel()
  122. search_window.title(&#39;Search options&#39;)
  123. search_window.geometry(&#39;250x160&#39;)
  124. search_window.resizable(False, False)
  125. search_window.configure(bg=&#39;#293556&#39;)
  126. file_path = tkinter.Label(search_window, width=35, wraplength=150)
  127. file_path.grid(row=0, column=0, sticky=&#39;nw&#39;, padx=(15, 5), pady=(15, 0))
  128. # Search based on the file name (ex: name or name.extension)
  129. file_name = tkinter.Label(search_window, width=35, wraplength=150)
  130. file_name.grid(row=1, column=0, sticky=&#39;nw&#39;, padx=(15, 5), pady=(15, 0))
  131. # Search files with the associated extension (ex: all .txt files)
  132. extension = tkinter.Label(search_window, width=35, wraplength=150)
  133. extension.grid(row=2, column=0, sticky=&#39;nw&#39;, padx=(15, 5), pady=(15, 0))
  134. start_searching = tkinter.Button(search_window, text=&#39;Start searching&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  135. start_searching.grid(row=4, column=0, sticky=&#39;nw&#39;, padx=15, pady=(15, 0))
  136. def on_window_close():
  137. self.window_already_open = False
  138. search_window.destroy()
  139. search_window.protocol(&quot;WM_DELETE_WINDOW&quot;, on_window_close)
  140. # Search functionality (button and description of the functionality)
  141. search_option = tkinter.Button(self.operations_frame, text=&#39;Search&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;,
  142. command=search_details)
  143. search_option.grid(row=0, column=0, sticky=&#39;nw&#39;, padx=15, pady=(15, 0))
  144. search_description = tkinter.Label(self.operations_frame,
  145. text=&#39;Search description&#39;)
  146. search_description.grid(row=0, column=0, sticky=&#39;nw&#39;, padx=70, pady=(18, 0))
  147. # Sort functionality (button and description of the functionality)
  148. sort_option = tkinter.Button(self.operations_frame, text=&#39;Sort&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  149. sort_option.grid(row=1, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  150. sort_description = tkinter.Label(self.operations_frame,
  151. text=&#39;Sort description&#39;)
  152. sort_description.grid(row=1, column=0, sticky=&#39;nw&#39;, padx=55, pady=(7, 0))
  153. # Delete functionality (button and description of the functionality)
  154. delete_option = tkinter.Button(self.operations_frame, text=&#39;Delete&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  155. delete_option.grid(row=2, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  156. delete_description = tkinter.Label(self.operations_frame,
  157. text=&#39;Delete description&#39;)
  158. delete_description.grid(row=2, column=0, sticky=&#39;nw&#39;, padx=105, pady=(7, 0))
  159. # Rename functionality (button and description of the functionality)
  160. rename_option = tkinter.Button(self.operations_frame, text=&#39;Rename&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  161. rename_option.grid(row=3, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  162. rename_description = tkinter.Label(self.operations_frame,
  163. text=&#39;Rename description&#39;)
  164. rename_description.grid(row=3, column=0, sticky=&#39;nw&#39;, padx=105, pady=(7, 0))
  165. # Duplication functionality (button and description of the functionality)
  166. duplication_option = tkinter.Button(self.operations_frame, text=&#39;Duplication&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  167. duplication_option.grid(row=4, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  168. duplication_description = tkinter.Label(self.operations_frame,
  169. text=&#39;Duplication description&#39;)
  170. duplication_description.grid(row=4, column=0, sticky=&#39;nw&#39;, padx=105, pady=(7, 0))
  171. # Permissions functionality (button and description of the functionality)
  172. permissions_option = tkinter.Button(self.operations_frame, text=&#39;Permissions&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  173. permissions_option.grid(row=5, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  174. permissions_description = tkinter.Label(self.operations_frame,
  175. text=&#39;Permissions description&#39;)
  176. permissions_description.grid(row=5, column=0, sticky=&#39;nw&#39;, padx=105, pady=(7, 0))
  177. # Compare functionality (button and description of the functionality)
  178. compare_option = tkinter.Button(self.operations_frame, text=&#39;Compare&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  179. compare_option.grid(row=6, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  180. compare_description = tkinter.Label(self.operations_frame,
  181. text=&#39;Compare description&#39;)
  182. compare_description.grid(row=6, column=0, sticky=&#39;nw&#39;, padx=105, pady=(7, 0))
  183. # Preview functionality (button and description of the functionality)
  184. preview_option = tkinter.Button(self.operations_frame, text=&#39;Preview&#39;, bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  185. preview_option.grid(row=7, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  186. preview_description = tkinter.Label(self.operations_frame,
  187. text=&#39;Preview description&#39;)
  188. preview_description.grid(row=7, column=0, sticky=&#39;nw&#39;, padx=105, pady=(7, 0))
  189. # Compression/ decompression functionality (button and description of the functionality)
  190. compression_decompression_option = tkinter.Button(self.operations_frame, text=&#39;Compression/ Decompression&#39;,
  191. bg=&#39;#294F63&#39;, fg=&#39;white&#39;)
  192. compression_decompression_option.grid(row=8, column=0, sticky=&#39;nw&#39;, padx=15, pady=(5, 0))
  193. compression_decompression_description = tkinter.Label(self.operations_frame,
  194. text=&#39;Compression/ decompression description&#39;)
  195. compression_decompression_description.grid(row=8, column=0, sticky=&#39;nw&#39;, padx=205, pady=(7, 0))
  196. # Window running loop
  197. self.root.mainloop()
  198. if __name__ == &#39;__main__&#39;:
  199. MainBox()
  200. Hello!
  201. ![Main window problem](https://i.stack.imgur.com/c7GKb.jpg)
  202. ![Search window problem](https://i.stack.imgur.com/lF3YX.jpg)
  203. I don&#39;t know how to fix the main window frames. I don&#39;t know if only the log frame is problematic or just there are multiple problems in multiple frames.
  204. Operations frame (350) + log frame (100) = 450 - the full height of the root frame.
  205. Why the dimensions are acting different than what I expected?
  206. Also, I don&#39;t understand the span of the labels in the search window and why I can&#39;t enter anything when the window is active (I can&#39;t type anything in them).
  207. Thank you in advance!
  208. I&#39;ve read the documentation but I can&#39;t figure it out.
  209. I tried to modify the height mostly since in my logic that should be the issue, but with no success.
  210. </details>
  211. # 答案1
  212. **得分**: 1
  213. 1. 如果您的框架都为空Math 350 + 100将起作用但是当您将其他小部件放入操作框架中使用gridpack方法),其高度将不再是350而只能足够容纳其中的所有小部件您可以看到其高度刚好在compression_decompression_description标签之后结束)。了解更多信息 [在这里][1]因此如果要使框架的大小恒定可以使用grid_propagate方法因此在创建框架后添加它
  214. self.operations_frame = tkinter.Frame(self.root, width=700,
  215. height=350, bg='#293556')
  216. self.operations_frame.grid_propagate(False)
  217. self.operations_frame.grid(row=0, sticky='ew')
  218. 如果将在其他框架中创建子小部件可以考虑采取相同的方法
  219. 2. 标签的宽度不是以像素为单位测量的而是以字符或文本单元为单位其中一个单元通常等于零符号0的宽度因此宽度为35的标签大约可以容纳35个零
  220. 3. 我是否正确理解您正在尝试在标签中输入内容它们没有这样的功能请改用EntryText小部件
  221. 还可以改进的内容
  222. I. 在您的代码中您可以使用继承Tk()根类中创建您的类例如`class MainBox(tkinter.Tk)`这可以使代码更清晰易读/理解
  223. II. 可能不必执行350+100您可以使用rowconfigure并设置weight参数为1例如这将使框架占用所有可用空间这将减少使用这样的数学计算的需要因此例如在root.configure之后添加以下内容
  224. self.root.resizable(False, False)
  225. self.root.configure(bg='red')
  226. self.root.rowconfigure(0, weight=1)
  227. 并将操作框架的sticky更改为ewns”,例如`self.operations_frame.grid(row=0, sticky='ewns')`通过使用此方法您无需使用grid_propagate也可以在不指定宽度和高度参数的情况下将框架留空例如`self.operations_frame = tkinter.Frame(self.root, bg='#293556')`
  228. III. 对于搜索窗口我还会删除行`search_window.geometry('250x160')`在我看来如果窗口与其中的小部件匹配那将更好因此通过更改它们窗口也将更改这是可选的
  229. IV. 我不太喜欢您如何对齐选项描述小部件我认为最好创建一些额外的框架看起来您试图从Deletepreview以相同的水平位置创建描述框架因此您可以为它们创建一个框架然后只需将描述放入第一列即可对于其余的小部件搜索排序和comp/decomp),可以为每个按钮+标签创建单独的框架然后类似的操作再次强调这可以帮助减少对padx的数学计算或猜测
  230. [1]: https://stackoverflow.com/questions/45087645/why-are-frames-resizing-when-using-python-tkinter
  231. <details>
  232. <summary>英文:</summary>
  233. 1. Math 350 + 100 will work, if your frames are both empty. But when you put other widgets to the operations frame (using grid or pack methods), its height will become not 350, but just enough to fit all widgets in it (you can see, that its height finishes just after the compression_decompression_description label). Read more about this [there][1]. So, if you want to make frames size constant, you can use grid_propagate method. So add it after you&#39;ve created the frame(s):
  234. self.operations_frame = tkinter.Frame(self.root, width=700,
  235. height=350, bg=&#39;#293556&#39;)
  236. self.operations_frame.grid_propagate(False)
  237. self.operations_frame.grid(row=0, sticky=&#39;ew&#39;)
  238. maybe do the same thing for other frame, if you will create child widgets in it as well.
  239. 2. Labels width is measured not in pixels, but in &quot;characters&quot; or text units, which one unit is usually equal to the width of the zero symbol (0). so labels width of 35 could fit approximately 35 zeros.
  240. 3. Am l right that you are trying to enter something in labels? They have no such functionality. Use Entry or Text widgets instead please.
  241. What could also be improved:
  242. I. Use inheritance, in your code you can make your class from a Tk(), root class, like `class MainBox(tkinter.Tk)`. Makes code clearer and easier to read/understand.
  243. II. Probably instead of doing 350+100, you could use rowconfigure with weight parameter to 1 for example. This will make frame occupy all available space. It will reduce the need of using such math. So add this after root.configure for example, like this:
  244. self.root.resizable(False, False)
  245. self.root.configure(bg=&#39;red&#39;)
  246. self.root.rowconfigure(0, weight=1)
  247. And change sticky of the operation frame to &quot;ewns&quot; so like `self.operations_frame.grid(row=0, sticky=&#39;ewns&#39;)`. By using this you don&#39;t need to use grid_propagate and also you can leave the frame without specifying width and height parameters, so `self.operations_frame = tkinter.Frame(self.root, bg=&#39;#293556&#39;)`
  248. III. For the search window, I would also remove line `search_window.geometry(&#39;250x160&#39;)`. In my opinion it is better, if the window will match the widgets in it, so by changing them window will be changing as well. This is optional.
  249. IV. I don&#39;t really like how you grid &quot;option&quot;s and &quot;description&quot;s widgets. I think it is better to create some extra frames. It seems that you are trying to make description frames from &quot;Delete&quot; to &quot;preview&quot; starts in the same horizontal position. So you can create a frame for them, and just put your descriptions in column 1. For the rest widgets (search, sort and comp/decomp) you can create a separate frames for each Button+Label, and then similar things. Again, this all can help to reduce math or guessing the numbers for padx.
  250. [1]: https://stackoverflow.com/questions/45087645/why-are-frames-resizing-when-using-python-tkinter
  251. </details>

huangapple
  • 本文由 发表于 2023年8月5日 06:24:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76839396.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定