簡體   English   中英

tkinter.LabelFrame 與 Checkbutton labelwidget

[英]tkinter.LabelFrame with Checkbutton labelwidget

tkinter ,我想要一個類似於LabelFrame的框架,但帶有一個Checkbutton作為標簽。

閱讀LabelFrame 源代碼后,我看到了labelwidget選項並嘗試

checkbutton = tk.Checkbutton(text=text)
checkbutton_frame = tk.LabelFrame(window, labelwidget=checkbutton)

它在視覺上工作,但Checkbutton最終成為window ( window.winfo_children() ) 的子級。 或者:

checkbutton_frame = tk.LabelFrame(window)
checkbutton = tk.Checkbutton(checkbutton_frame, text="Hello, frame")
checkbutton_frame.configure(labelwidget=checkbutton)

使Checkbutton成為Checkbutton的子LabelFrame LabelFrame的默認內置Label不會出現在winfo_children 因為我在添加所有小部件后遞歸地設置了padxpady ,所以讓Checkbutton中的winfo_children通過將Checkbutton移出其錨定位置來破壞布局。 是否有一個好的,干凈的方式來代替一CheckbuttonLabelLabelFrame維持一致的(即沒有任何)后代的關系? 歡迎使用其他解決方法的答案。

最小化復制

import tkinter as tk

def pack_configure_recursive(widget, **kwargs):
    stack = list(widget.winfo_children())
    while stack:
        descendent = stack.pop()
        try:
            stack.extend(descendent.winfo_children())
        except Exception:
            pass
        try:
            descendent.pack_configure(**kwargs)
        except Exception:
            pass


class CheckbuttonFrame(tk.LabelFrame):
    def __init__(self, master=None, **kwargs):
        def pop_kwarg(name):
            nonlocal kwargs
            if name in kwargs:
                result = kwargs[name]
                del kwargs[name]
                return result
            else:
                return None

        text = pop_kwarg("text")
        self.variable = pop_kwarg("variable")
        self.command = pop_kwarg("command")

        tk.LabelFrame.__init__(self, master, **kwargs)
        self.configure(labelwidget=tk.Checkbutton(text=text, variable=self.variable, command=self.handler))  # Use this to make a child of the window
        # self.configure(labelwidget=tk.Checkbutton(self, text=text, variable=self.variable, command=self.handler))  # Use this to make a child of the frame

    def update_state(self):
        if self.variable:
            state = 'normal' if self.variable.get() else 'disable'
            stack = list(self.winfo_children())
            while stack:
                descendent = stack.pop()
                try:
                    stack.extend(descendent.winfo_children())
                except Exception:
                    pass
                try:
                    descendent.configure(state=state)
                except tk.TclError:
                    pass

    def handler(self):
        self.update_state()

        if self.command:
            external_command = self.command
            external_command()


window = tk.Tk()
option = tk.IntVar()
checkbutton_frame = CheckbuttonFrame(window, text="My option group", variable=option)
checkbutton_frame.pack()
tk.Label(checkbutton_frame, text="More widgets here").pack()
checkbutton_frame.update_state()
pack_configure_recursive(window, padx=2, pady=2)  # This line break the layout
window.mainloop()

LabelFrame 的默認內置 Label 不會出現在 winfo_children 中

那是因為LabelFrame的內置標簽不是小部件。

是否有一種不錯的、干凈的方法可以用 Checkbutton 替換 LabelFrame 中的 Label 以保持一致(即沒有任何)后代關系? 歡迎使用其他解決方法的答案。

不,那里沒有。 小部件必須是某些東西的后代,根本無法繞過它。 從邏輯上講,它可能應該是 labelframe 本身的后代。

您必須自動重新打包小部件的任何代碼都需要跳過此小部件。

您調用pack_configure代碼可能應該忽略任何未由 pack 管理的小部件,您可以這樣做:

if descendent.winfo_manager() == "pack":
    descendent.pack_configure(**kwargs)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM