在tkinter中调整输入框大小

0 投票
1 回答
10072 浏览
提问于 2025-04-18 17:17

下面这个简单的例子是关于一个有水平和垂直滚动条的窗口。这个窗口里有一个输入框,用来显示当前的工作目录。不过,因为输入框太小,里面的文字看不全。我希望当用户放大窗口时,能够显示更多的文字。请问我该如何调整下面的例子,让输入框(在UserFileInput里定义的)随着窗口的大小变化而变化呢?我试过使用 window.grid_columnconfigure(见下面的代码),但似乎没有什么效果。看起来这是使用画布(canvas)时出现的问题,因为之前我能让输入框自动调整大小,但我需要画布来放置水平和垂直的滚动条。

window.grid(row=0, column=0, sticky='ew')
window.grid_columnconfigure(0, weight=1)

(还有在列=1的情况下)但这也没有效果。

import Tkinter as tk
import tkFileDialog
import os

class AutoScrollbar(tk.Scrollbar):
    def set(self, lo, hi):
        if float(lo) <= 0.0 and float(hi) >= 1.0:
            # grid_remove is currently missing from Tkinter!
            self.tk.call("grid", "remove", self)
        else:
            self.grid()
        tk.Scrollbar.set(self, lo, hi)

class Window(tk.Frame):

    def UserFileInput(self,status,name):
        row = self.row
        optionLabel = tk.Label(self)
        optionLabel.grid(row=row, column=0, sticky='w')
        optionLabel["text"] = name
        text = status#str(dirname) if dirname else status
        var = tk.StringVar(root)
        var.set(text)
        w = tk.Entry(self, textvariable= var)
        w.grid(row=row, column=1, sticky='ew')
        w.grid_columnconfigure(1,weight=1)
        self.row += 1
        return w, var

    def __init__(self,parent):
        tk.Frame.__init__(self,parent)

        self.row = 0
        currentDirectory = os.getcwd()
        directory,var = self.UserFileInput(currentDirectory, "Directory")


if __name__ == "__main__":
    root = tk.Tk()
    root.grid_columnconfigure(0, weight=1)
    root.grid_rowconfigure(0,weight=1)

    vscrollbar = AutoScrollbar(root,orient=tk.VERTICAL)
    vscrollbar.grid(row=0, column=1, sticky='ns')
    hscrollbar = AutoScrollbar(root, orient=tk.HORIZONTAL)
    hscrollbar.grid(row=1, column=0, sticky='ew')

    canvas=tk.Canvas(root,yscrollcommand=vscrollbar.set,xscrollcommand=hscrollbar.set)
    canvas.grid(row=0, column=0, sticky='nsew')
    vscrollbar.config(command=canvas.yview)
    hscrollbar.config(command=canvas.xview)


    window = Window(canvas)
    canvas.create_window(0, 0, anchor=tk.NW, window=window)
    window.update_idletasks()
    canvas.config(scrollregion=canvas.bbox("all"))

    root.mainloop()

1 个回答

1

你的代码里有几个问题正在阻碍你。最大的障碍是你把一个框架放在了画布里。这种做法很少必要,而且让你的代码变得比需要的更复杂。你为什么要使用画布?还有,你为什么代码的一部分用类,而其他部分又不用呢?

不管怎样,你有两个问题:

  1. 当窗口变大时,框架没有跟着变大,所以窗口里的内容也不能变大。
  2. 标签不会变大,因为你错误地使用了 grid_columnconfigure

可视化问题的提示

在解决布局问题时,一个非常有用的技巧是暂时给每个包含的控件上不同的颜色,这样你就能看到每个控件的位置。例如,把画布涂成粉色,把 Window 框架涂成蓝色,这样就能清楚地看到 Window 框架也没有调整大小。

调整框架大小

因为你选择把控件嵌入到画布里,所以当包含的画布改变大小时,你需要手动调整框架的宽度。你可以通过在画布上设置一个绑定,让它在每次调整大小时调用一个函数。你可以使用的事件是 <Configure>。注意:这个绑定不仅在大小变化时触发,但你可以安全地忽略这一点。

这个函数需要计算画布的宽度,从而得出框架的期望宽度(减去你想要的任何边距)。然后你需要配置框架,使其具有这个宽度。为了方便,你需要保留框架的画布ID引用,或者给框架一个独特的标签。

这里有一个假设框架标签为 "frame" 的函数:

def on_canvas_resize(event):
    padding = 8
    width = canvas.winfo_width() - padding
    canvas.itemconfigure("frame", width=width)

你需要调整创建画布项的方式,以包括这个标签:

canvas.create_window(..., tags=["frame"])

最后,设置一个绑定,当控件大小变化时触发:

canvas.bind("<Configure>", on_canvas_resize)

使用 grid_columnconfigure 让标签调整大小

你需要在 包含 控件上使用 grid_columnconfigure。你希望框架内部的列能够伸缩,而不是标签内部的列。

你需要把这一行改成:

w.grid_columnconfigure(...)

改成这样:

self.grid_columnconfigure(...)

撰写回答