Tkinter应用程序在Win和Linux上的行为不同

时间:2017-08-10 08:10:32

标签: python linux windows tkinter autoscroll

我最近开始学习Tkinter,昨天我注意到在Win 10和Xubuntu 16.04系统上运行时,相同代码与相同的Python 2.7存在奇怪的行为差异。

以下是我正在处理的代码(这意味着可能存在许多其他错误:)):

from random import choice
from string import ascii_uppercase

import Tkinter as tk

class Manager(tk.Canvas):

    counter = 0
    previously_focused = 0

    def __init__(self, master=None, **kwargs):
        tk.Canvas.__init__(self,master,**kwargs)
        self.frame = tk.Frame(self)
        self.create_window(0,0,anchor=tk.N+tk.W,window=self.frame)
        self.row = 0
        self.widgets = {}
        self.lookup_entry = None

        self.frame.bind("<Configure>", lambda event, canvas=self: self.onFrameConfigure())

    def onFrameConfigure(self):
        '''
        Reset the scroll region to encompass the inner frame
        '''
        self.configure(scrollregion=self.bbox("all"))

    def __set__(self, e_id):
        '''
        Dummy that "sets" the value that the user has entered in the entry.
        In addition it also resets the background of the entry
        '''
        print("Setting \"" + self.widgets[e_id]["label"].cget("text") + "\" to \"" + str(self.widgets[e_id]["value"].get()) + "\"")
        self.widgets[e_id]["value"]["background"]="white"

    def __select_all__(self, event):
        entry = event.widget
        entry.select_range(0, tk.END)
        entry.icursor(0)

    def add_entry(self):
        '''
        Creates an entry conisting of a label, entry and button, adds it to the grid and stores
        it in a dictionary for easier access
        '''
        label = tk.Label(self.frame, text="".join(choice(ascii_uppercase) for i in range(12)) + "_" +str(self.counter))
        label.grid(row = self.row,column = 0)
        entry = tk.Entry(self.frame, background="white")
        entry.bind("<Control-KeyRelease-a>", self.__select_all__)
        entry.grid(row = self.row,column = 1)
        button = tk.Button(self.frame, text="Set", command=lambda counter=self.counter: self.__set__(str(counter)))
        button.grid(row = self.row,column = 2)
        self.widgets[str(self.counter)] = {"label": label, "value":entry, "button":button, "position":self.row}
        self.row += 1
        self.counter += 1

    def lookup(self, e_id):
        '''
        Automatically focuses and scrolls to the entry of the given id
        if found. In addition it also changes the background of that entry.

        If user enters an id that cannot be parsed (to int), nothing happens
        '''
        try:
            if self.previously_focused != int(e_id):
                self.widgets[str(self.previously_focused)]["value"]["background"]="white"

            if e_id not in self.widgets:
                print("Unable to find entry with id \"" + e_id + "\"")
                return

            print(self.widgets[e_id]["label"].cget("text"))
            self.widgets[e_id]["value"]["background"]="orange"
            self.widgets[e_id]["value"].focus()
            self.yview_moveto(0) # Adjust the Y offset of the canvas so that we always start from the top
            self.yview_scroll(self.widgets[e_id]["position"], tk.UNITS) # Scroll downwards to the given entry
            self.previously_focused = int(e_id)
        except ValueError:
            print("Id needs to be an integer")

if __name__ == "__main__":
    root = tk.Tk()

    scroll = tk.Scrollbar(root)
    scroll.grid(row=0,column=0,sticky=tk.N+tk.S)
    manager = Manager(root)
    manager.grid(row=0,column=1)
    manager.config(yscrollcommand = scroll.set)
    scroll.config(command=manager.yview)

    add_button = tk.Button(root, text = "+", command=manager.add_entry)
    add_button.grid(row=1,column=0)

    frame_lookup = tk.Frame(root)
    lookup_entry = tk.Entry(frame_lookup)
    lookup_entry.grid(row=0,column=0)
    lookup_button = tk.Button(frame_lookup, text="Find, focus & scroll to", command=lambda: manager.lookup(lookup_entry.get()))
    lookup_button.grid(row=0,column=1)
    frame_lookup.grid(row=1, column=1)

    root.mainloop()

我已经修改了这里的代码(对不起,忘了我从哪里得到它)。基本上单击 + 按钮可以在上面的网格中添加一个元素(在允许我使用垂直滚动条的画布内)。每个元素都包含一个标签(<random-12-characters-sequence>_<increment-counter>),条目和一个几乎不做任何事情的虚拟按钮。重要的部分是底部的字段以及按钮查找,焦点和&amp; scrollto 即可。每当用户输入有效ID时,应用程序会自动聚焦ID所属元素的条目并滚动到该条目,以便它在视线范围内。其余的代码并不重要。

视觉差异的出现是我非常清楚的(右:Linux,左:Win):

enter image description here enter image description here

我的问题在于应用程序在自动滚动功能方面的行为方式。正如您在Linux上看到的那样,我总是可以通过内部聚焦条目获得元素的完整视图。在Win上,只有当该元素没有向上/向下滚动房间时才会发生。

自动滚动的工作方式是我首先将画布的偏移重置为(0,0),然后从那里滚动X UNITS,其中X是增量计数器,也是充当网格中元素位置的信息源。

知道为什么会这样吗? Win上的UNITS是否可能与Linux上的UNITS不同?

0 个答案:

没有答案