与继承的 Tkinter Text 元素不同的网格行为 [英] Different grid behavior from inherited Tkinter Text element

查看:26
本文介绍了与继承的 Tkinter Text 元素不同的网格行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这里的另一个答案,用户创建了一个继承的 TextWithVar 类,该类提供实例Tkinter.Text 元素,但具有像 Tkinter.Entry 那样的 textvariable 功能.但是,在测试中,当使用网格管理器时,这个新类的行为与 Text 元素不同.为了演示,此代码是从该答案中复制的,并在最后添加了一些测试调用:

In another answer here, a user created an inherited TextWithVar class that provides instances of the Tkinter.Text element but with textvariable functionality like Tkinter.Entry has. However, in testing, this new class behaves differently than a Text element when when using the Grid manager. To demonstrate, this code is copied from that answer, with the addition of some test calls at the end:

import Tkinter as tk

class TextWithVar(tk.Text):
    '''A text widget that accepts a 'textvariable' option'''
    def __init__(self, parent, *args, **kwargs):
        try:
            self._textvariable = kwargs.pop("textvariable")
        except KeyError:
            self._textvariable = None

        tk.Text.__init__(self, *args, **kwargs)

        # if the variable has data in it, use it to initialize
        # the widget
        if self._textvariable is not None:
            self.insert("1.0", self._textvariable.get())

        # this defines an internal proxy which generates a
        # virtual event whenever text is inserted or deleted
        self.tk.eval('''
            proc widget_proxy {widget widget_command args} {

                # call the real tk widget command with the real args
                set result [uplevel [linsert $args 0 $widget_command]]

                # if the contents changed, generate an event we can bind to
                if {([lindex $args 0] in {insert replace delete})} {
                    event generate $widget <<Change>> -when tail
                }
                # return the result from the real widget command
                return $result
            }
            ''')

        # this replaces the underlying widget with the proxy
        self.tk.eval('''
            rename {widget} _{widget}
            interp alias {{}} ::{widget} {{}} widget_proxy {widget} _{widget}
        '''.format(widget=str(self)))

        # set up a binding to update the variable whenever
        # the widget changes
        self.bind("<<Change>>", self._on_widget_change)

        # set up a trace to update the text widget when the
        # variable changes
        if self._textvariable is not None:
            self._textvariable.trace("wu", self._on_var_change)

    def _on_var_change(self, *args):
        '''Change the text widget when the associated textvariable changes'''

        # only change the widget if something actually
        # changed, otherwise we'll get into an endless
        # loop
        text_current = self.get("1.0", "end-1c")
        var_current = self._textvariable.get()
        if text_current != var_current:
            self.delete("1.0", "end")
            self.insert("1.0", var_current)

    def _on_widget_change(self, event=None):
        '''Change the variable when the widget changes'''
        if self._textvariable is not None:
            self._textvariable.set(self.get("1.0", "end-1c"))

root = tk.Tk()
text_frame = TextWithVar(root)
text_frame.grid(row=1, column=1)
test_button = tk.Button(root, text='Test')
test_button.grid(row=1, column=1, sticky='NE')
root.mainloop()

root2 = tk.Tk()
frame = tk.Frame(root2)
frame.grid(row=1, column=1)
text_frame2 = TextWithVar(frame)
text_frame2.grid(row=1, column=1)
test_button2 = tk.Button(frame, text='Test')
test_button2.grid(row=1, column=1, sticky='NE')
root2.mainloop()

在这个例子中,当 TextWithVar 元素直接位于 root 内部时,它的行为就像它应该的那样 - Button 元素被放置在它上面的角落.但是,当两者都在 Frame 内时, Button 元素无处可见.现在将 TextWithVar 调用更改为 tk.Text.它们都以应有的方式工作,按钮清晰可见.根据创建新类的 Bryan 的说法,这些应该以完全相同的方式工作,我倾向于同意这一点.那么为什么它们的工作方式不同?

In this example, when the TextWithVar element is directly inside root, it acts like it should - the Button element is placed on top of it in the corner. However, when both are inside a Frame, the Button element is nowhere to be seen. Now change both the TextWithVar calls to tk.Text. Both of them work the way they should, with the Button in plain view. According to Bryan, who made the new class, these should work the exact same way, which I tend to agree with. So why do they work differently?

推荐答案

这是TextWithVar的一个bug,在这行代码中:

It's a bug in TextWithVar, in this line of code:

tk.Text.__init__(self, *args, **kwargs)

代码需要包含parent参数:

tk.Text.__init__(self, parent, *args, **kwargs)

这篇关于与继承的 Tkinter Text 元素不同的网格行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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