Tkinter performance issues between Windows and Linux

Robert Okadar aranea.network at gmail.com
Fri Apr 12 13:18:10 EDT 2019


Hi community,

I have developed a tkinter GUI component, Python v3.7. It runs very well in
Linux but seeing a huge performance impact in Windows 10. While in Linux an
almost real-time performance is achieved, in Windows it is slow to an
unusable level.

The code is somewhat stripped down from the original, but the performance
difference is the same anyway. The columns can be resized by clicking on
the column border and dragging it. Resizing works only for the top row (but
it resizes the entire column).
In this demo, all bindings are avoided to exclude influence on the
component performance and thus not included. If you resize the window
(i.e., if you maximize it), you must call the function table.fit() from
IDLE shell.

Does anyone know where is this huge difference in performance coming from?
Can anything be done about it?

Thank you,
--
Robert Okadar
IT Consultant

Schedule an *online meeting <https://calendly.com/aranea-network/60min>* with
me!

Visit *aranea-mreze.hr* <http://aranea-mreze.hr> or call
* +385 91 300 8887*
-------------- next part --------------

import tkinter

class Resizer(tkinter.Frame):
    def __init__(self, info_grid, master, **cnf):
        self.table_grid = info_grid
        tkinter.Frame.__init__(self, master, **cnf)
        self.bind('<Button1-Motion>', self.resize_column)
        self.bind('<ButtonPress-1>', self.resize_start)
        self.bind('<ButtonRelease-1>', self.resize_end)
        self._resizing = False

        self.bind('<Destroy>', self.onDestroyEvent)

    def onDestroyEvent(self, event):
        self.table_grid = []

    def resize_column(self, event, width = None):
        #if self._resizing:
        top = self.table_grid.Top
        grid = self.table_grid._grid
        col = self.master.grid_info()["column"]
        if not width:
            width = self._width + event.x_root - self._x_root
        top.columnconfigure(col, minsize = width)
        grid.columnconfigure(col, minsize = width)
        

    def resize_start(self, event):
        top = self.table_grid.Top
        self._resizing = True
        self._x_root = event.x_root
        col = self.master.grid_info()["column"]
        self._width = top.grid_bbox(row = 0, column = col)[2]
        #print event.__dict__
        
        col = self.master.grid_info()["column"]
        #print top.grid_bbox(row = 0, column = col)

    def resize_end(self, event):
        pass
        #self.table_grid.xscrollcommand()
        #self.table_grid.column_resize_callback(col, self)


class Table(tkinter.Frame):
    def __init__(self, master, columns = 10, rows = 20, width = 100,**kw):
        tkinter.Frame.__init__(self, master, **kw)
        self.columns = []
        self._width = width
        self._grid = grid = tkinter.Frame(self, bg = "#CCCCCC")
        self.Top = top = tkinter.Frame(self, bg = "#DDDDDD")
        self.create_top(columns)
        self.create_grid(rows)
        

        #self.bind('<Configure>', self.on_table_configure)
        #self.bind('<Map>', self.on_table_map)

        top.pack(anchor = 'nw')#, expand = 1, fill = "both")
        grid.pack(anchor = 'nw')#fill = "both",expand = 1

    def on_table_map(self, event):
        theight = self.winfo_height()

    def fit(self):#on_table_configure(self, event):
        i = 0
        for frame in self.Top.grid_slaves(row = 0):
            frame.resizer.resize_column(None, width = frame.winfo_width())
            i += 1
        theight = self.winfo_height()
        fheight = self._grid.winfo_height() + self.Top.winfo_height()
        #print('<Map>', theight, fheight)
        if theight > fheight:
            rheight = self.grid_array[0][0].winfo_height()
            ammount = int((-fheight + theight) / rheight)
            #print(rheight, ammount)
            for i in range(ammount):
                self.add_row()
                self.update()
        

    def add_row(self, ammount = 1):
        columnsw = self.columns
        row = []
        i = len(self.grid_array)
        for j in range(len(columnsw)):
            bg = self.bgcolor0
            if i % 2 == 1:
                bg = self.bgcolor1
            entry = tkinter.Label(self._grid, bg = bg, text = '%i %i' % (i, j))
            entry.grid(row = i, column = j, sticky = "we", padx = 2)
            row.append(entry)
        self.grid_array.append(row)
        
        
    bgcolor0 = "#FFFFFF"
    bgcolor1 = "#EEEEEE"
    def create_grid(self, height):
        
        #grid.grid(row = 0, column = 0, sticky = "nsew")
        
        columnsw = self.columns# = self.Top.grid_slaves(row = 1)
        self.grid_array = []
        for i in range(height):
            row = []
            for j in range(len(columnsw)):
                bg = self.bgcolor0
                if i % 2 == 1:
                    bg = self.bgcolor1
                #entry = self.EntryClass(False, self, self._grid, bg = bg, width = 1, )
                entry = tkinter.Label(self._grid, bg = bg, text = '%i %i' % (i,j))
                entry.grid(row = i, column = j, sticky = "we", padx = 2)
                row.append(entry)
            self.grid_array.append(row)

    def create_top(self, columns = 10):
        top = self.Top
        #columns = self._columns #maybe to rename
        for i in range(columns):
            name = 'column %i' % i
            self.add_column(name, top)
        

    def add_column(self, name, top, width = None):
        if not width:
            width = self._width
        col = tkinter.Frame(top)
        i = len(self.columns)
        #filter = Filter(self, name, i, top)
        entry = tkinter.Entry(col, width = 1) #readonlybackground
        #col.ColumnIndex = i
        #col.array_index = i
        entry.insert(0, name)
        resizer = Resizer(self, col, bg = "#000000", width = 3, height = 21, cursor = 'sb_h_double_arrow')
        #entry.grid(row = 0, column = 0, sticky = "we")
        #resizer.grid(row = 0, column = 1, sticky = "e")
        entry.pack(side = "left", fill = "both", expand = 1)
        resizer.pack(side = "right")
        top.columnconfigure(i, minsize = width, weight = 1)
        #filter.grid(row = 0, column = i, sticky = "we")
        col.grid(row = 0, column = i, sticky = "we")
        col.entry = entry
        #col.filter = filter
        #col.index = filter.index = i
        col.resizer = resizer
        #filter.Column = col
        entry.Column = col
        self.columns.append(col)

if __name__ == '__main__':
    columns = 30
    rows = 20
    width = 60
    root = tkinter.Tk()
    root.wm_title('TableGridTest')
    table = self = Table(root, columns = columns, rows = rows, width = width)
    table.pack(expand = 1, fill = 'both')
    #table.create_grid(


More information about the Python-list mailing list