在 tkinter 中抖动边界

Posted

技术标签:

【中文标题】在 tkinter 中抖动边界【英文标题】:Jiggling borders in tkinter 【发布时间】:2021-12-05 19:27:42 【问题描述】:

在 tk/tkinter 中构建一个包含大量不同大小的框架的界面,所有这些框架都将填充有按钮、标签和文本字段(大量的 frame.pack() 和 frame.destroy 正在进行)。我决定首先用 6x4 网格填充根框架,然后根据需要用临时框架覆盖它。我的主要目标是根据用户的纵横比调整框架/标签的大小(遵守我建立的行/列权重),然后让边框在传播后锁定到位。

下面是我所说的简化示例(颜色仅用于间距/清晰度):

import random


class CharacterInterface:
    def __init__(self, master):
        self.display_text = ['']
        self.master = master
        self.master.attributes('-fullscreen', True)
        self.master.title("Interface Template")
        self.master.configure(bg='#000000')

        # generates a 6x4 grid to underpin the interface/keep things spaced out
        for i in range(6):
            for j in range(4):
                self.master.grid_columnconfigure(i, weight=1)
                self.master.grid_rowconfigure(j, weight=1)
                self.dummy_frame = tk.Frame(self.master, relief=tk.RIDGE, borderwidth=4,
                                            bg='#' + str(2 * j) + str(2 * j) + str(2 * j) + str(i) + str(i) + str(i))
                self.dummy_label = tk.Label(master=self.dummy_frame,
                                            bg='#' + str(i) + str(i) + str(i) + str(2 * j) + str(2 * j) + str(2 * j))
                self.dummy_frame.grid(row=j, column=i, sticky='nsew')
                self.dummy_label.pack(ipadx=8, ipady=8, fill="both", expand=True)

        self.ch_frame = tk.Frame(self.master, bg='#000077')
        self.ch_frame.grid(row=0, column=0, rowspan=2, columnspan=3, sticky="nsew")
        self.ch_frame.grid_propagate(False)                     # this locks ch_frame's right border
        self.ch_frame.grid_columnconfigure(0, weight=1)
        self.ch_frame.grid_columnconfigure(1, weight=3)
        self.ch_frame.grid_rowconfigure(0, weight=1)
        self.ch_frame.grid_rowconfigure(1, weight=6)
        self.chtop_label = tk.Label(master=self.ch_frame, relief=tk.RIDGE, borderwidth=4, fg="#FFFFFF", bg='#000000',
                                    font=('Courier', 12), justify="left", anchor='nw')
        self.chtop_label.grid(row=0, column=0, columnspan=2, sticky='nsew')
        self.chleft_label = tk.Label(master=self.ch_frame, relief=tk.RIDGE, borderwidth=4, fg="#FFFFFF", bg='#000000',
                                     font=('Courier', 12), justify="left", anchor='nw')
        self.chleft_label.grid(row=1, column=0, sticky='nsew')
        self.chright_label = tk.Label(master=self.ch_frame, relief=tk.RIDGE, borderwidth=4, fg="#FFFFFF",
                                      bg='#000000', font=('Courier', 12), justify="left", anchor='nw')
        self.chright_label.grid(row=1, column=1, sticky='nsew')

        self.test_button = tk.Button(self.chright_label, text="test", bg='#000000', fg="#FFFFFF",
                                      font=('Courier', 12), relief=tk.FLAT, anchor='w', command=lambda: self.toss())
        self.test_button.pack(side='left')

    def toss(self):
        self.test_button.pack_forget()
        str_length, str_instance = random.randrange(1, 10), ""
        for i in range(str_length):
            str_instance = str_instance + 'a'
        self.chleft_label['text'] = str_instance
        self.test_button.pack(side='left')


root = tk.Tk()
my_gui = CharacterInterface(root)
root.mainloop()

所以这里形成了 6x4 网格,并且 self.ch_frame.grid_propagate(False) 设置锁定在 ch_frame 的右边框(我创建的三个标签的父框架)。但是,如果您单击按钮,它将在 chleft_label 中创建一个小字符串,并且中间标签边框开始在我身上摆动。

有没有办法让我在不使用 place() 或分配宽度值的情况下将边框锁定到位?我想我可以在 chleft_label 中粘贴一个占位符字符串,但我更愿意使用传播命令而不是糟糕的解决方法来锁定它(我将处理大量这些帧)。我也可以通过放弃 ch_frame 中的网格格式来解决它,但是我失去了一些我想要的核心功能(仅根据需要更新框架/标签)。

这是一个死胡同,试图在网格/包界面中断言这种边界定位吗?

谢谢!

【问题讨论】:

只是想知道:你有什么系统(Mac、Windows、Linux)?我运行了你的代码,没有任何抖动。我使用的是 Linux(特别是 Ubuntu)。 感谢您运行它。我已经在两台机器(Windows 10 和 Windows 7)上运行它,并且在两种情况下都会发生抖动。如果您反复按下按钮,chleft_label 和 chright_label 之间的边界位置会根据 chleft_label 中测试字符串的长度而移动。 啊,有道理。我误解了摇晃是什么意思。是的,当我运行它时,它实际上确实这样做了。会调查它... 你在创建self.chleft_label时尝试设置宽度选项吗? 尝试在两个self.ch_frame.grid_columnconfigure(...) 中添加uniform=1。顺便说一句,当我在创建 self.chleft_label 时设置 width=10 时,我没有得到任何 jiggling 【参考方案1】:

@acw1668 搞定了——我只需要在我的self.ch_frame.grid_columnconfigure()s 中添加一个uniform=1 参数。文档中的定义正盯着我看:

“分配属于统一组的列的空间,以便它们的大小始终与其-weight值严格成比例”

【讨论】:

请务必接受您的回答,以便其他用户知道该问题已得到满意回答。很高兴你终于想通了! :-)

以上是关于在 tkinter 中抖动边界的主要内容,如果未能解决你的问题,请参考以下文章

Python Tkinter Checkbutton 与其他小部件对齐

Python Tkinter参考资料之(通用控件属性)

Python Tkinter之布局

Python3 tkinter,怎么在Label/Canvas中插入图片?

Tkinter循环“Tkinter没有响应”

在 Tkinter 中拖放?