Tkinter 的带有 wrap=none 的文本无法水平滚动超过可见行的宽度

HYB*_*ING 5 python textbox tkinter tcl horizontal-scrolling

当我注意到如果长行不可见时, ScrolledText 小部件的水平滚动条将消失时,我一直在修改PAGE滚动小部件的实现。事实证明这与水平滚动条无关,是原始的 Tk 行为

路径名 xview

返回包含两个元素的列表。每个元素都是 0 到 1 之间的实数分数;它们一起描述了窗口中可见的文档水平范围的部分。例如,如果第一个元素为 0.2,第二个元素为 0.6,则 20% 的文本位于左侧屏幕外,中间 40% 在窗口中可见,40% 的文本位于屏幕外 -屏幕右侧。分数仅指窗口中实际可见的行:如果窗口中的行都很短,因此它们完全可见,则返回的分数将为 0 和 1,即使窗口中还有其他行比窗口宽得多的文本。

使用自动隐藏滚动条,垂直滚动会使水平滚动条不断缩小、变宽,有时会消失(随后影响垂直滚动条)。

我怎样才能规避这个问题?

相关来源(主要由 PAGE 生成,还有我为另一个滚动小部件添加的一些内容):

class AutoScroll(object):
    """Configure the scrollbars for a widget."""

    def __init__(self, master, cbl=None):
        try:
            vsb = ttk.Scrollbar(master, orient='vertical', command=self.yview)
        except:
            pass
        hsb = ttk.Scrollbar(master, orient='horizontal', command=self.xview)

        try:
            self.configure(yscrollcommand=self._autoscroll(vsb, cbl))
        except:
            pass
        self.configure(xscrollcommand=self._autoscroll(hsb, cbl))

        self.grid(column=0, row=0, sticky='nsew')
        try:
            vsb.grid(column=1, row=0, sticky='ns')
        except:
            pass
        hsb.grid(column=0, row=1, sticky='ew')

        master.grid_columnconfigure(0, weight=1)
        master.grid_rowconfigure(0, weight=1)
        # Copy geometry methods of master (taken from ScrolledText.py)

        methods = (
            Pack.__dict__.keys() |
            Grid.__dict__.keys() |
            Place.__dict__.keys()
        )

        for meth in methods:
            if (meth[0] != "_" and meth not in ("config", "configure") and
                    meth not in type(self).__bases__[0].__dict__):
                setattr(self, meth, getattr(master, meth))

    def clscroll(self, cbl):
        # Checklist elements scroll
        root.update()
        for i, w in enumerate(cbl[1]):
            bb = ttk.Treeview.bbox(self, i, "#0")
            if bb == "":
                w.place_forget()
            else:
                x, y, _, _ = bb
                w.place(x=x+(tvhh-2)/2, y=y+tvrh/2, anchor='center')
                cbl[0].place(x=x+(tvhh-2)/2, anchor='center')
        root.update()

    # @staticmethod
    def _autoscroll(self, sbar, cbl):
        """Hide and show scrollbar as needed."""
        def wrapped(first, last):
            if cbl:
                self.clscroll(cbl)
            first, last = float(first), float(last)
            if first <= 0 and last >= 1:
                sbar.grid_remove()
            else:
                sbar.grid()
            sbar.set(first, last)
        return wrapped

    def __str__(self):
        return str(self.master)

def _create_container(func):
    """Creates a ttk Frame with a given master, and use this new frame to
    place the scrollbars and the widget."""
    def wrapped(cls, master, **kw):
        container = ttk.Frame(master)
        return func(cls, container, **kw)
    return wrapped

class ScrolledText(AutoScroll, Text):
    """A standard Tkinter Text widget with scrollbars that will
    automatically show/hide as needed."""
    @_create_container
    def __init__(self, master, **kw):
        Text.__init__(self, master, **kw)
        AutoScroll.__init__(self, master)
Run Code Online (Sandbox Code Playgroud)

蜥蜴编辑

较短的先生:

class AutoScroll(object):
    """Configure the scrollbars for a widget."""

    def __init__(self, master, cbl=None):
        try:
            vsb = ttk.Scrollbar(master, orient='vertical', command=self.yview)
        except:
            pass
        hsb = ttk.Scrollbar(master, orient='horizontal', command=self.xview)

        try:
            self.configure(yscrollcommand=self._autoscroll(vsb, cbl))
        except:
            pass
        self.configure(xscrollcommand=self._autoscroll(hsb, cbl))

        self.grid(column=0, row=0, sticky='nsew')
        try:
            vsb.grid(column=1, row=0, sticky='ns')
        except:
            pass
        hsb.grid(column=0, row=1, sticky='ew')

        master.grid_columnconfigure(0, weight=1)
        master.grid_rowconfigure(0, weight=1)
        # Copy geometry methods of master (taken from ScrolledText.py)

        methods = (
            Pack.__dict__.keys() |
            Grid.__dict__.keys() |
            Place.__dict__.keys()
        )

        for meth in methods:
            if (meth[0] != "_" and meth not in ("config", "configure") and
                    meth not in type(self).__bases__[0].__dict__):
                setattr(self, meth, getattr(master, meth))

    def clscroll(self, cbl):
        # Checklist elements scroll
        root.update()
        for i, w in enumerate(cbl[1]):
            bb = ttk.Treeview.bbox(self, i, "#0")
            if bb == "":
                w.place_forget()
            else:
                x, y, _, _ = bb
                w.place(x=x+(tvhh-2)/2, y=y+tvrh/2, anchor='center')
                cbl[0].place(x=x+(tvhh-2)/2, anchor='center')
        root.update()

    # @staticmethod
    def _autoscroll(self, sbar, cbl):
        """Hide and show scrollbar as needed."""
        def wrapped(first, last):
            if cbl:
                self.clscroll(cbl)
            first, last = float(first), float(last)
            if first <= 0 and last >= 1:
                sbar.grid_remove()
            else:
                sbar.grid()
            sbar.set(first, last)
        return wrapped

    def __str__(self):
        return str(self.master)

def _create_container(func):
    """Creates a ttk Frame with a given master, and use this new frame to
    place the scrollbars and the widget."""
    def wrapped(cls, master, **kw):
        container = ttk.Frame(master)
        return func(cls, container, **kw)
    return wrapped

class ScrolledText(AutoScroll, Text):
    """A standard Tkinter Text widget with scrollbars that will
    automatically show/hide as needed."""
    @_create_container
    def __init__(self, master, **kw):
        Text.__init__(self, master, **kw)
        AutoScroll.__init__(self, master)
Run Code Online (Sandbox Code Playgroud)