python-3.x 文本框和底部按钮之间的某种虚拟分割

uqzxnwby  于 2023-02-01  发布在  Python
关注(0)|答案(1)|浏览(137)

我有一个文本框,我想它的大小将适合窗口大小。可能吗?
问题是按钮(在toplevel窗口中)消失了。有没有可能得到小窗口,仍然显示按钮与包?我告诉了关于“show_changes”功能
它应该是文本框和底部按钮之间的某种虚拟分割。

import tkinter as tk
from tkinter import *

def show_changes(root):
    newWindow = Toplevel(root)
    newWindow.title("Changes")
    newWindow.geometry("1000x100+200+200")
    frame = Frame(newWindow)
    frame.pack(side=tk.TOP, fill=BOTH, expand=True)
    verscrlbar_frame1 = Scrollbar(frame, orient="vertical")
    horscrlbar_frame1 = Scrollbar(frame, orient="horizontal")
    verscrlbar_frame1.pack(side='right', fill='y')
    horscrlbar_frame1.pack(side='bottom', fill='x')

    changes_txt = Text(frame, wrap=NONE)
    changes_txt.pack(side=tk.TOP, fill=BOTH, expand=True)
    changes_txt.config(xscrollcommand=horscrlbar_frame1.set)
    changes_txt.config(yscrollcommand=verscrlbar_frame1.set)
    changes_txt.config(state=DISABLED)

    verscrlbar_frame1.config(command=changes_txt.yview)
    horscrlbar_frame1.config(command=changes_txt.xview)

    frame_btn = Frame(newWindow)
    frame_btn.pack(side=tk.BOTTOM, expand=False)
    ok_btn = Button(frame_btn, text="Ok")
    ok_btn.pack(side=tk.LEFT, pady=10)

    newWindow.mainloop()

def main():
    root = tk.Tk()
    root.geometry("200x200")  # Size of the window
    root.title("Main Window")
    btn = Button(root, text="show_changes", command=lambda: show_changes(root))
    btn.pack()

    root.mainloop()

# ----------------------------------------------------------------------
if __name__ == "__main__":
    main()

谢谢你,亚历克斯

ilmyapht

ilmyapht1#

在使用pack时,小部件的打包顺序很重要,当窗口不够大,无法按要求的大小显示所有小部件时(代码中就是这种情况),pack将从最后添加的小部件开始收缩小部件。
至少有三种解决方案,每种都将独立地解决问题,但这三种都是最佳实践。
首先,您可以选择 * 不 * 给予窗口一个明确的大小。相反,让小部件达到所需的最小大小,并让tkinter计算窗口大小。这是最好的解决方案。例如,如果文本小部件只需要2行高,则将其高度设置为2,然后删除对newWindow.geometry的调用(或者,让它留在里面但只用它来设置位置)。Tkinter会计算一个窗口大小,刚好够容纳按钮和2行文本小部件。
第二种解决方案是将文本小部件的高度设置为很小的值,然后使用pack使其填充可用空间,其原因是当小部件不适合固定大小的窗口时,压缩器必须开始收缩或移除小部件。2它将收缩所有的小部件(一次一个...)直到它们都达到最小请求大小。一旦发生这种情况,它必须实际开始切掉一个或多个小部件的一部分。你的文本小部件最小请求大小是默认的20行高,因为这个窗口不适合,所以打包器开始删除最后添加的小部件,即按钮。
第三种解决方案是利用tkinter会按照“堆叠顺序”来缩小或移除小部件,这与小部件的添加顺序相反。换句话说,它会缩小并移除最后一个要打包的小部件,然后是倒数第二个,以此类推。如果你先打包按钮所在的框架,然后再打包文本小部件,当打包器必须开始减少窗口小部件以使其适合时,打包器将缩小文本窗口小部件而不是按钮。
我建议将所有的解决方案结合起来,因为它们都代表了您应该养成习惯的最佳实践。

  • 使文本小部件的高度仅为所需高度
  • 在打包文本小部件之前,先打包带有按钮的框架
  • 不要给予窗口一个固定的大小;让tkinter帮你计算一下

此外,您不需要第二次调用mainloop,也不应该导入tkinter两次。最后,我发现将小部件中所有子控件对packplacegrid的调用分组在一起,可以更容易地可视化代码中的布局,并使维护更容易。
结合所有这些建议,我将如下重写函数:

import tkinter as tk

def show_changes(root):
    newWindow = tk.Toplevel(root)
    newWindow.title("Changes")
    newWindow.geometry("+200+200")

    frame_btn = tk.Frame(newWindow)
    frame = tk.Frame(newWindow)

    # pack the widgets in the order that they should be clipped
    # if the window is too small. That usually means toolbars and
    # menubars first, "hero" widgets like a Text or Canvas last.
    frame_btn.pack(side=tk.BOTTOM, expand=False)
    frame.pack(side=tk.TOP, fill="both", expand=True)

    ok_btn = tk.Button(frame_btn, text="Ok")
    ok_btn.pack(side=tk.LEFT, pady=10)

    verscrlbar_frame1 = tk.Scrollbar(frame, orient="vertical")
    horscrlbar_frame1 = tk.Scrollbar(frame, orient="horizontal")
    changes_txt = tk.Text(frame, height=2, width=80, wrap="none")

    changes_txt.config(xscrollcommand=horscrlbar_frame1.set)
    changes_txt.config(yscrollcommand=verscrlbar_frame1.set)
    changes_txt.config(state="disabled")
    verscrlbar_frame1.config(command=changes_txt.yview)
    horscrlbar_frame1.config(command=changes_txt.xview)

    verscrlbar_frame1.pack(side='right', fill='y')
    horscrlbar_frame1.pack(side='bottom', fill='x')
    changes_txt.pack(side=tk.TOP, fill="both", expand=True)

    newWindow.mainloop()

def main():
    root = tk.Tk()
    root.geometry("200x200")  # Size of the window
    root.title("Main Window")
    btn = tk.Button(root, text="show_changes", command=lambda: show_changes(root))
    btn.pack()

    root.mainloop()

# ----------------------------------------------------------------------
if __name__ == "__main__":
    main()

相关问题