删除内容后如何在Tkinter中缩小帧? [英] How to shrink a frame in tkinter after removing contents?

查看:103
本文介绍了删除内容后如何在Tkinter中缩小帧?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的大多数主题都涉及如何缩小内容的Frame,但是我感兴趣的是在破坏了所述内容后将其缩小.这是一个示例:

Most of the topics I came across deals with how to not shrink the Frame with contents, but I'm interested in shrinking it back after the destruction of said contents. Here's an example:

import tkinter as tk
root = tk.Tk()
lbl1 = tk.Label(root, text='Hello!')
lbl1.pack()
frm = tk.Frame(root, bg='black')
frm.pack()
lbl3 = tk.Label(root, text='Bye!')
lbl3.pack()
lbl2 = tk.Label(frm, text='My name is Foo')
lbl2.pack()

到目前为止,我应该在我的窗口中看到它:

So far I should see this in my window:

Hello!
My name is Foo
Bye!

那太好了,但是我想根据需要保持中间层的可互换性和隐藏性.因此,如果我破坏其中的lbl2:

That's great, but I want to keep the middle layer interchangeable and hidden based on needs. So if I destroy the lbl2 inside:

lbl2.destroy()

我想看:

Hello!
Bye!

但是我看到的却是:

Hello!
███████
Bye!

我想将frm缩小到基本上不存在,因为我想保持我的主要小部件的顺序不变.理想情况下,我想运行frm.pack(fill=tk.BOTH, expand=True)以便我的小部件可以相应缩放.但是,如果这妨碍了收缩,我可以不用fill/expand生存.

I want to shrink frm back to basically non-existence because I want to keep the order of my main widgets intact. Ideally, I want to run frm.pack(fill=tk.BOTH, expand=True) so that my widgets inside can scale accordingly. However if this interferes with the shrinking, I can live without fill/expand.

我尝试了以下操作:

  1. pack_propagate(0):实际上,这完全不会扩展帧到pack()之后.
  2. 重新运行frm.pack():但是这破坏了我的主要小部件的顺序.
  3. .geometry(''):仅在root窗口上有效-对于Frame不存在.
  4. frm.config(height=0):奇怪的是,这似乎并没有改变任何东西.
  5. frm.pack_forget():来自这个答案,但是并没有带回来.
  1. pack_propagate(0): This actually doesn't expand the frame at all past pack().
  2. Re-run frm.pack(): but this ruins the order of my main widgets.
  3. .geometry(''): This only works on the root window - doesn't exist for Frames.
  4. frm.config(height=0): Oddly, this doesn't seem to change anything at all.
  5. frm.pack_forget(): From this answer, however it doesn't bring it back.

它给我留下的唯一选择是使用grid管理器,我认为它可以工作,但不完全是我想要的...,所以我很想知道是否还有另一种方法可以实现这一目标./p>

The only option it leaves me is using a grid manager, which works I suppose, but not exactly what I'm looking for... so I'm interested to know if there's another way to achieve this.

推荐答案

问题:删除最后小部件后缩小Frame?

Question: Shrink a Frame after removing the last widget?

绑定到<'Expose'>事件,如果没有孩子,则绑定.configure(height=1).

Bind to the <'Expose'> event and .configure(height=1) if no children.

参考:

只要重新绘制窗口小部件的全部或部分,就会生成Expose事件

An Expose event is generated whenever all or part of a widget should be redrawn

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()

        tk.Label(self, text='Hello!').pack()
        self.frm = frm = tk.Frame(self, bg='black')
        frm.pack()
        tk.Label(self, text='Bye!').pack()
        tk.Label(frm, text='My name is Foo').pack()

        self.menubar = tk.Menu()
        self.config(menu=self.menubar)
        self.menubar.add_command(label='delete', command=self.do_destroy)
        self.menubar.add_command(label='add', command=self.do_add)

        frm.bind('<Expose>', self.on_expose)

    def do_add(self):
        tk.Label(self.frm, text='My name is Foo').pack()
        
    def do_destroy(self):
        w = self.frm
        if w.children:
            child = list(w.children).pop(0)
            w.children[child].destroy()

    def on_expose(self, event):
        w = event.widget
        if not w.children:
            w.configure(height=1)
        
                            
if __name__ == "__main__":
    App().mainloop()


问题:重新运行frm.pack():但是这破坏了我的主要小部件的顺序.
frm.pack_forget(),但是它并没有带回来.

Question: Re-run frm.pack(): but this ruins the order of my main widgets.
frm.pack_forget(), however it doesn't bring it back.

Pack具有选项before=after.这样可以打包相对于其他窗口小部件的窗口小部件.

Pack has the options before= and after. This allows to pack a widget relative to other widgets.

参考:

将其主服务器用作从属服务器的主服务器,并在打包顺序中将其他从服务器插入其他服务器之前.

Use its master as the master for the slaves, and insert the slaves just before other in the packing order.

使用before=self.lbl3作为锚点的示例.如果没有子级,请使用.pack_forget()删除Frame,并在装箱单中的同一位置重新包装.

Example using before= and self.lbl3 as anchor. The Frame are removed using .pack_forget() if no children and get repacked at the same place in the packing order.

注意:我只显示相关部分!

Note: I show only the relevant parts!


class App(tk.Tk):
    def __init__(self):
        ...
        self.frm = frm = tk.Frame(self, bg='black')
        frm.pack()
        self.lbl3 = tk.Label(self, text='Bye!')
        self.lbl3.pack()
        ...

    def on_add(self):
        try:
            self.frm.pack_info()
        except:
            self.frm.pack(before=self.lbl3, fill=tk.BOTH, expand=True)

        tk.Label(self.frm, text='My name is Foo').pack()

    def on_expose(self, event):
        w = event.widget
        if not w.children:
            w.pack_forget()

使用Python测试:3.5-'TclVersion':8.6'TkVersion':8.6

这篇关于删除内容后如何在Tkinter中缩小帧?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆