Можете ли вы изменить родителя виджета в python tkinter? - PullRequest
13 голосов
/ 09 июня 2011

Есть ли способ изменить родителя виджета (в данном случае tt.f.frame)?Я не могу найти ключевые слова для использования в виджетах .config .Разве это не возможно в Python Tkinter?Функционально мне бы хотелось, чтобы мой текущий кадр был помещен в мой виджет tkk.notebook, а когда я дважды щелкну по вкладке, чтобы все было в рамке вкладки, переместился в свое отдельное окно TopLevel.Таким образом, пользователь может иметь визуальную ссылку на эту вкладку, работая на другой вкладке.Я не мог придумать никакого другого способа добиться этого без функционала фрейма, о котором я спрашиваю.Возможно, если кто-нибудь сможет обойти эту проблему, мне не нужно беспокоиться о возможностях родительского виджета.

Cheers, Chris

Ответы [ 2 ]

9 голосов
/ 10 июня 2011

старый пост Фредрика Лунда (автора Tkinter) предполагает, что невозможно изменить родителя виджета.

0 голосов
/ 31 марта 2019

Вы не можете переместить виджет или группу виджетов к новому родителю, но вы можете смоделировать это с помощью некоторых простых процедур.Я не работаю в Python, но вы должны быть в состоянии преобразовать следующий код в tkinter из tcl.Под симуляцией я подразумеваю, что вы копируете виджет и любых детей рекурсивно новому родителю.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
...