TKinter place the buttons very slowly. My code puts a large number of buttons in the form of a table using already optimized loops. When you click on any button, it is destroyed and the code is executed in which the column and row of this button are needed. But this code works very slowly - it takes about 2 seconds to display a field of 30x30 buttons. I've optimized everything I could (set the values of the side and y variables so that they are not calculated many times) but it doesn't help.
from tkinter import *
import threading
import time
class UI:
def _setcell(row, column):
pass
def window(rows, columns, a):
root = Tk()
root.geometry(f"{rows*(a 6)}x{columns*(a 6)}")
root.resizable(False, False)
root.title("Tkinter window")
field_frame = Frame(width=rows*(a*a), height=columns*(a*a), bg="#293133", colormap="new")
field_frame.pack(side=BOTTOM)
field_frame.grid_propagate(False)
pixelVirtual = PhotoImage(width=1, height=1)
def btns():
start_time = time.time()
btnarr = []
side = a 6
for row in range(rows):
rowl = []
y=side*row
for column in range(columns):
rowl.append(Button(field_frame, text="", image=pixelVirtual, height = a, width = a, command=
lambda row=row, column=column: [btnarr[row][column].place_forget(), __class__._setcell(row, column)]))
rowl[column].place(x=column*side, y=y)
btnarr.append(rowl)
print("--- %s seconds ---" % (time.time() - start_time))
btn_thread = threading.Thread(target=btns)
btn_thread.start()
root.mainloop()
UI.window(30, 30, 16)
CodePudding user response:
There is a great deal of micro management in your code. Tkinter is clever and can easily handle positioning and size of widgets. I've replaced pack and place with grid manager and removed threading as I couldn't find any reference to btns.
Here is a modified version of your code that works.
It takes about 10 seconds to display 900 buttons with images. The image used is 131x136 and subsampled to 22x23 which allows all buttons to be visible on my monitor.
The addition of a blank image of equal dimensions and a change to _setcell
maintains button positioning and prevents annoying changes to overall UI size.
from tkinter import *
filepath = "Arrow.gif"
blakpath = "Black.gif"
class UI:
def _setcell(self, row, column):
self.btnarr[row][column].config(
image = self.blankVirtual, command = '')
def window(self, rows, columns):
self.root = Tk()
self.root.title("Tkinter window")
field_frame = Frame(self.root, bg="#293133", colormap="new")
field_frame.grid(sticky = NSEW)
self.pixelVirtual = PhotoImage(file = filepath).subsample(6,6)
# w, h = self.pixelVirtual.width(), self.pixelVirtual.height()
self.blankVirtual = PhotoImage(file = blakpath).subsample(6,6)
btnarr = []
for row in range(rows):
rowA = []
for column in range(columns):
rowA.append(Button(field_frame, image = self.pixelVirtual))
rowA[~0].grid(row = row, column = column, sticky = NSEW)
rowA[~0]["command"] = lambda row = row, column = column: [self._setcell(row, column)]
btnarr.append(rowA)
app = UI()
app.window(30, 30)
app.root.mainloop()
