滚动太快时,Tkinter无法在Windows操作系统中更新

时间:2018-08-02 15:49:30

标签: windows python-3.x tkinter scrollbar

Fields Not Showing

如上例所示,滚动速度太快时,左列的Label对象或右列的Entry对象不会混合显示。

如果我单击滚动条并快速拖动,它看起来可能像这样糟糕。如果我使用鼠标滚轮缓慢滚动,通常很好,尽管有时无论滚动速度如何,都会错过一行。作为参考,它似乎总是与缓慢滚动时未显示的同一行。

来回更改选项卡会使所有内容再次正确绘制。在Linux上,一切正常。但这也需要在Windows上工作。

不确定是否重要,但是每一行都是Canvas内部的Frame中的Label和Entry,画布与滚动条一起位于Frame内部。每个顶部框架都是笔记本中的“页面”,以提供顶部显示的标签。

最后是一些问题。我可以添加一个按钮来强制重绘而不破坏并重新创建它吗?也许我可以在创建这些对象时添加一些内容,以迫使它们在移动时重绘?

根据要求提供示例代码:

#!/usr/bin/env python3
from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText

class WriteableEntry(Label):
    def __init__(self, name, value, *args, **kwargs):
        #~ self.ip = ip
        #~ self.ping_results = []
        super(WriteableEntry, self).__init__(*args, **kwargs)

        self.label = name
        self.init_value = value
        self.written_value = ''

        self.field_name = Label(self, justify="left", text=name, width=25)
        self.field_value = Entry(self, justify='left', width=60)
        self.field_value.insert(END, value)
        self.field_name.pack(side=LEFT)
        self.field_value.pack(side=LEFT)


class InfoFrame(Frame):
    def __init__(self, *args, **kwargs):
        super(InfoFrame, self).__init__(*args, **kwargs)

        self.nb_frame = Frame(self, height=300, width=730)
        self.nb_frame.pack_propagate(False)
        self.nb = ttk.Notebook(self.nb_frame)
        self.nb.pressed_index = None

        filler = {}
        for x in range(0, 3):
            for y in ('a', 'b', 'c', 'd', 'e', 'f', 'g'):
                filler.update({"out%d_%s" % (x, y):"nada"})
        self.example_dict = {'A':filler, 'B':filler, 'C':filler}

        print("E_D:\n", self.example_dict)

        for page in sorted(self.example_dict):
            print("page:\t", page)
            entry_count = len(self.example_dict[page])
            #   #   ## Make new_page to put in nb
            new_page = Frame(self.nb)
            new_page.pack(fill=BOTH, expand=True)
            #   #   ## Make canvas to put in that new_page
            canvas = Canvas(new_page)
            scroll = Scrollbar(new_page, command=canvas.yview)
            ## Orig *27
            canvas.config(yscrollcommand=scroll.set, scrollregion=(0,120,120,entry_count * 35))
            canvas.pack(side=LEFT, fill=BOTH, expand=True)
            scroll.pack(side=RIGHT, fill=Y)
            #   #   ## Make a frame to put in that canvas
            canvas_frame = Frame(canvas, bg='white', width=50, height=50)
            ## Orig +12 *10
            canvas.create_window(345, (entry_count + 12) * 13, window=canvas_frame)
            for value in sorted(self.example_dict[page]):
                print("value:\t", value)
                writeable_entry = WriteableEntry(value, self.example_dict[page][value], master=canvas_frame)
                writeable_entry.pack(side=TOP)

            self.nb.add(new_page, text=page)
        self.nb.pack(side=TOP, expand=True, fill="both")

        self.nb_frame.pack(side=RIGHT, expand=True, fill=BOTH)


class IPLabel(LabelFrame):
    def __init__(self, *args, **kwargs):
        super(IPLabel, self).__init__(*args, **kwargs)
        self.info_frame = InfoFrame(master=self)
        self.info_frame.grid(row=1, columnspan=2, sticky=E + W)


class AvailableApplication(Frame):
    def __init__(self, master):
        super(AvailableApplication, self).__init__(master)
        #~ self.ips = ips
        self.grid()
        self.grid_propagate(True)
        self.ip_widgets = []
        self.createWidgets()

    def createWidgets(self):
        self.ip_frame = Frame(self)
        self.ip_widgets = []
        ip_widget = IPLabel(master=self.ip_frame)
        ip_widget.grid(row=0, column=1, columnspan=4, sticky=E + W)
        self.ip_widgets.append(ip_widget)
        self.ip_frame.grid(row=1, column=0, columnspan=8)
        self.ip_frame.grid_propagate(True)


if __name__ == "__main__":
    root = Tk()
    root.title("Example Script")
    app = AvailableApplication(root)
    app.mainloop()
    root.destroy()

1 个答案:

答案 0 :(得分:1)

主要问题是WriteableEntry。它不是tk.Label。您不能拥有tk.Label的子窗口小部件(tk.Entrytk.Label)。您也为此工作使用了错误的布局管理器。可能还因为错误的子窗口小部件使用。您依靠pack管理器的包装行为。别。使用grid()管理器。

由于某些原因,标签C不可见,但这是另一个问题。 使用Ctrl-Tab,我发现有第三个标签,但标签文本为空字符串。使用

添加标签
self.nb.add(new_page, text="P"+page)

使其更清晰可见。我不知道为什么选项卡名称“ C” 对于tkinter具有特殊含义

杀死应用程序和窗口的唯一可能方法是使用Close按钮。那么,为什么要破坏根窗口?它已经被破坏了。

#!/usr/bin/env python3
from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText

class WriteableEntry(object):
    def __init__(self, name, value, *args, **kwargs):
        #~ self.ip = ip
        #~ self.ping_results = []
        #super(WriteableEntry, self).__init__(*args, **kwargs)

        master = kwargs['master']
        row = kwargs['row']
        self.label = name
        self.init_value = value
        self.written_value = ''

        self.field_name = Label(master, justify="left", text=name, width=25)
        self.field_value = Entry(master, justify='left', width=60)
        self.field_value.insert(END, value)
        self.field_name.grid(row=row, column=0)
        self.field_value.grid(row=row, column=1)


class InfoFrame(Frame):
    def __init__(self, *args, **kwargs):
        super(InfoFrame, self).__init__(*args, **kwargs)

        self.nb_frame = Frame(self, height=300, width=730)
        self.nb_frame.pack_propagate(False)
        self.nb = ttk.Notebook(self.nb_frame)
        self.nb.pressed_index = None

        filler = {}
        for x in range(0, 3):
            for y in ('a', 'b', 'c', 'd', 'e', 'f', 'g'):
                filler.update({"out%d_%s" % (x, y):"nada"})
        self.example_dict = {'A':filler, 'B':filler, 'C':filler}

        print("E_D:\n", self.example_dict)

        for page in sorted(self.example_dict):
            print("page:\t", page)
            entry_count = len(self.example_dict[page])
            #   #   ## Make new_page to put in nb
            new_page = Frame(self.nb)
            new_page.pack(fill=BOTH, expand=True)
            #   #   ## Make canvas to put in that new_page
            canvas = Canvas(new_page)
            scroll = Scrollbar(new_page, command=canvas.yview)
            ## Orig *27
            canvas.config(yscrollcommand=scroll.set, scrollregion=(0,120,120,entry_count * 35))
            canvas.pack(side=LEFT, fill=BOTH, expand=True)
            scroll.pack(side=RIGHT, fill=Y)
            #   #   ## Make a frame to put in that canvas
            canvas_frame = Frame(canvas, bg='white', width=50, height=50)
            ## Orig +12 *10
            canvas.create_window(345, (entry_count + 12) * 13, window=canvas_frame)
            for row, value in enumerate(sorted(self.example_dict[page])):
                print("value:\t", value)
                writeable_entry = WriteableEntry(value, self.example_dict[page][value], master=canvas_frame, row=row)
                #writeable_entry.pack(side=TOP)

            self.nb.add(new_page, text="P"+page)
        self.nb.pack(side=TOP, expand=True, fill="both")

        self.nb_frame.pack(side=RIGHT, expand=True, fill=BOTH)


class IPLabel(LabelFrame):
    def __init__(self, *args, **kwargs):
        super(IPLabel, self).__init__(*args, **kwargs)
        self.info_frame = InfoFrame(master=self)
        self.info_frame.grid(row=1, columnspan=2, sticky=E + W)


class AvailableApplication(Frame):
    def __init__(self, master):
        super(AvailableApplication, self).__init__(master)
        #~ self.ips = ips
        self.grid()
        self.grid_propagate(True)
        self.ip_widgets = []
        self.createWidgets()

    def createWidgets(self):
        self.ip_frame = Frame(self)
        self.ip_widgets = []
        ip_widget = IPLabel(master=self.ip_frame)
        ip_widget.grid(row=0, column=1, columnspan=4, sticky=E + W)
        self.ip_widgets.append(ip_widget)
        self.ip_frame.grid(row=1, column=0, columnspan=8)
        self.ip_frame.grid_propagate(True)


if __name__ == "__main__":
    root = Tk()
    root.title("Example Script")
    app = AvailableApplication(root)
    app.mainloop()
    #root.destroy()