【问题标题】:Can you change a widget's parent in python tkinter?你可以在 python tkinter 中更改小部件的父级吗?
【发布时间】:2011-06-08 21:44:19
【问题描述】:

有没有办法改变一个小部件(在这种情况下是 ttk.frame)的父级?我在小部件 .config 中找不到任何要使用的关键字。这在 python tkinter 中是不可能的吗?我想要的功能是在我的 tkk.notebook 小部件中获取我当前的框架,当我双击选项卡时,将所有内容都放在选项卡的框架中,移动到它自己单独的 TopLevel 窗口。这样,用户可以在处理另一个选项卡时对该选项卡进行视觉参考。如果没有我要询问的框架功能,我想不出任何其他方式来实现这一点。也许如果有人能绕过这个问题,我就不需要担心父小部件的功能了。

干杯, 克里斯

【问题讨论】:

    标签: python widget tkinter frames parents


    【解决方案1】:

    Fredrik Lundh(Tkinter 的作者)的 old post 建议无法更改小部件的父级。

    【讨论】:

    • 嗯,这很不幸。不过还是谢谢。
    【解决方案2】:

    您不能将一个小部件或一组小部件移动到新的父级,但您可以使用一些简单的例程来模拟它。我不在 python 中工作,但您应该能够将以下代码从 tcl 转换为 tkinter。通过模拟,我的意思是您将小部件和任何孩子递归地复制到新的父级。 Tk 提供了精确复制要移动/复制的小部件的布局、绑定和外观所需的内省,包括所有子小部件。下面的例程将允许您将单个或复杂的小部件移动或复制到新的父级。

    proc getWidgetType { w } {
        set class [winfo class $w ]
        if { [ string index $class 0 ] eq "T" &&
         [ string match "\[A-Z\]" [string index $class 1 ] ] } {
            set class [string range [string tolower $class ] 1 end ]
            set class "ttk::$class"
        } else {
            set class [string tolower $class ]
        }
        return $class
    }
    proc getConfigOptions { w } {
        set configure [ $w configure ]
        set options {}
        foreach f $configure {
            if { [llength $f ] < 3 } { continue; } 
            set name    [ lindex $f 0 ]
            set default [ lindex $f end-1 ]
            set value   [ lindex $f end ]
            if { $default ne $value } {
                lappend options $name $value 
            }
        }
        return $options
    }
    proc copyWidget { w  newparent { level 0 } } {
        set type [ getWidgetType $w ]
        set name [ string trimright $newparent.[lindex [split $w "." ] end ] "." ]  
        set retval [ $type $name {*}[ getConfigOptions $w ] ]
        foreach b [ bind $w ] {
            puts "bind $retval $b [subst { [bind $w $b ] } ] " 
            catch { bind $retval $b  [subst { [bind $w $b ] } ] } 
        } 
        if { $level > 0 } {
            if { [ catch { pack info $w } err ] == 0 } {
                array set temp [ pack info $w ]
                array unset temp -in
                catch { pack $name {*}[array get temp ] } 
            } elseif { [ catch { grid info $w } err ] == 0 } {
                array set temp [ grid info $w ]
                array unset temp -in
                catch { grid $name {*}[array get temp ] } 
            }
        }
        incr level 
        if { [ pack slaves $w ] ne "" } { 
            foreach f [ pack slaves $w ] {
                copyWidget $f $name $level
            }
        } else {
            foreach f [winfo children $w ] {
                copyWidget $f $name $level
            }
        }
        return $retval
    }
    proc moveWidget { w newparent } {
        set retval [ copyWidget $w $newparent ]
        destroy $w
        return $retval
    }
    
    # assume we have already created a toplevel with complex layout named
    # .input with subframe .input.frame.tframe that we want to transfer to
    # a new toplevel .x .  There is a cancel button we want to transfer
    # also at .input.frame.bframe.icancel and we will grid it into
    # .x.tframe .
    
    toplevel .x
    set form [ moveWidget .input.frame.tframe .x ]
    set cancel [ moveWidget .input.frame.bframe.icancel .x.tframe ]
    grid $cancel -row 2 -column 2 -sticky new 
    pack $form -anchor center -expand 1 -fill both -side top
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多