root.update отстает в Linux, но не в Windows - PullRequest
0 голосов
/ 02 апреля 2019

Мой код Python Tkinter сильно отстает в Linux, но не в Windows.Это как-то связано с root.update () и root.config ().Как я могу это исправить, чтобы версия linux работала так же быстро, как и версия для Windows?

Я написал программу на python для Windows, которая работает хорошо.В настоящее время я делаю версию для Linux.После некоторой модификации версия для Linux работает как надо, за исключением огромного отставания.Я вставил код во время различных частей программы.Для линий root.update() и root.config() существуют большие различия между окнами и linux.

Следующие строки являются причиной задержки:

root.update()
root.config(menu=menubar)

Я запускал программу несколько раз в Windows и Linux и записывал количество времени, использованное для выполнения кода.

Ниже приведена запись времени выполнения строк:

В окнах:

root update:  0.47  seconds 
root update:  0.2656  seconds
root update:  0.3125  seconds
root update:  0.3594  second
root update:  0.3593  seconds
menubar root config done:  0.0081
menubar root config done:  0.0

В окнах: процесс завершен с кодом выхода -1

Pycharm в Windows использует Python 3.7


В Linux:

root update:  2.4416  seconds
root update:  87.3216  seconds
root update:  1.5798  seconds
root update:  148.2783  seconds
root update:  2.2533  seconds
root update:  2.2771  seconds
root update:  2.4898  seconds
root update:  8.022  seconds
root update:  171.6852  seconds
root update:  1.7088  seconds
menubar root config done:  0.0441
menubar root config done:  2.4566
menubar root config done:  1.2589

В Linux: процесс завершен с кодом выхода 9

Pycharmв Linux используется Python 3.6

Вот код, который настолько прост, насколько я могу это сделать.Существует графический интерфейс пользователя tkinter, запросы к базе данных mysql, функция, которая генерирует строку меню и множество виджетов, помещенных в сетку.

root = Tk()
root.title("KLUSTERBOX")

...

def main_frame(): # call function to make the main screen

# define and put widgets on a grid

...

generate_menubar(Frame) # call function to make menubar

# define the menubar

root.config(menu=menubar)

...

# define and put widgets on a grid

root.update()

Меня попросили MCVE.Это пример программы, которая дублирует проблему:

from tkinter import *
import time
import sys
def main_frame():
    starttime = time.time()
    F = Frame(root)
    F.pack(fill=BOTH, side=LEFT)
    C1 = Canvas(F)
    C1.pack(fill=BOTH, side=BOTTOM)
    Button(C1, text="Refresh", width=12, command=lambda: [F.destroy(),main_frame()]).pack(side=LEFT)
    Button(C1, text="Quit", width=12, command=root.destroy).pack(side=LEFT)
    # link up the canvas and scrollbar
    S = Scrollbar(F)
    C = Canvas(F, width=1600)
    S.pack(side=RIGHT, fill=BOTH)
    C.pack(side=LEFT, fill=BOTH, pady=10, padx=10)
    S.configure(command=C.yview, orient="vertical")
    C.configure(yscrollcommand=S.set)
    if sys.platform == "win32":
        C.bind_all('<MouseWheel>', lambda event: C.yview_scroll(int(-1 * (event.delta / 120)), "units"))
    elif sys.platform == "linux":
        C.bind_all('<Button-4>', lambda event: C.yview('scroll',-1,'units'))
        C.bind_all('<Button-5>', lambda event: C.yview('scroll',1,'units'))
    # create the frame inside the canvas
    preF=Frame(C)
    C.create_window((0, 0), window=preF, anchor=NW)
    Label(preF, text="To refresh - press REFRESH").pack()
    Label(preF, text="To quit - press QUIT").pack()
    Label(preF, text="Run times are displayed in console").pack()
    FF = Frame(C)
    C.create_window((0,108), window=FF, anchor=NW)
    for i in range(100):
        Button(FF, text=i, width=5, bg="yellow", anchor="w").grid(row=i,column=0)
        Button(FF, text="hello there", width=24, bg="yellow", anchor="w").grid(row=i,column=1)
        Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=2)
        Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i,column=3)
        Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=4)
        Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=5)
    endtime = time.time()
    print("runtime prior to root.update(): ", round(endtime - starttime,4), " seconds")
    starttime = time.time()
    root.update()
    endtime = time.time()
    print("root.update() runtime: ", round(endtime-starttime,4)," seconds")
    C.config(scrollregion=C.bbox("all"))
    mainloop()
root = Tk()
root.geometry("%dx%d+%d+%d" % (625,600,100,50))
main_frame()

Я рассчитал время выполнения для root.update() и root.config(menu=menubar).Время в linux слишком велико и может сделать программу непригодной для использования, особенно если учесть, что есть другая часть программы, которая значительно отстает.

1 Ответ

0 голосов
/ 04 апреля 2019

На моем Linux Mint это занимает 0,3 с (Python 3.7, 3.6, 2.7), и я не знаю, почему он так медленно работает на вашем Linux.

Вот только код с некоторыми изменениями - возможно, это поможет.

  • Я не использую root.update(), но after(), чтобы изменить scrollregion 100 мс после запуска основного цикла. До запуска mainloop виджеты не существовали и не могли вычислить область прокрутки.

  • Я не уничтожаю F со всеми виджетами, но я только создаю кадр кнопками, которые создают таблицу, и я воссоздаю только этот кадр.

  • Я не запускаю main_frame снова, поэтому я не запускаю другой mainloop()

  • Мне пришлось использовать global, чтобы сохранить доступ к кадру с таблицей, потому что command= не может получить значение из функции и привязки к переменной.

Старт занимает 0,3 с, а обновление занимает 0,09 с

.

from tkinter import *
import time
import sys

def create_table(C):
    table = Frame(C)

    C.create_window((0,108), window=table, anchor=NW)

    for i in range(100):
        Button(table, text=i, width=5, bg="yellow", anchor="w").grid(row=i,column=0)
        Button(table, text="hello there" + str(X), width=24, bg="yellow", anchor="w").grid(row=i,column=1)
        Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=2)
        Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i,column=3)
        Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=4)
        Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=5)

    return table

def refresh(C):
    global table

    starttime = time.time()

    table.destroy()
    table = create_table(C)

    endtime = time.time()

    print("refresh: ", round(endtime-starttime,4)," seconds")


def main_frame():
    global table

    starttime = time.time()

    F = Frame(root)
    F.pack(fill=BOTH, side=LEFT)

    C1 = Canvas(F)
    C1.pack(fill=BOTH, side=BOTTOM)

    Button(C1, text="Refresh", width=12, command=lambda:refresh(C)).pack(side=LEFT)
    Button(C1, text="Quit", width=12, command=root.destroy).pack(side=LEFT)

    # link up the canvas and scrollbar
    S = Scrollbar(F)
    C = Canvas(F, width=1600)
    S.pack(side=RIGHT, fill=BOTH)
    C.pack(side=LEFT, fill=BOTH, pady=10, padx=10)
    S.configure(command=C.yview, orient="vertical")
    C.configure(yscrollcommand=S.set)

    if sys.platform == "win32":
        C.bind_all('<MouseWheel>', lambda event: C.yview_scroll(int(-1 * (event.delta / 120)), "units"))
    elif sys.platform == "linux":
        C.bind_all('<Button-4>', lambda event: C.yview('scroll',-1,'units'))
        C.bind_all('<Button-5>', lambda event: C.yview('scroll',1,'units'))

    # create the frame inside the canvas
    preF=Frame(C)
    C.create_window((0, 0), window=preF, anchor=NW)
    Label(preF, text="To refresh - press REFRESH").pack()
    Label(preF, text="To quit - press QUIT").pack()
    Label(preF, text="Run times are displayed in console").pack()

    table = create_table(C)

    endtime = time.time()
    print("runtime: ", round(endtime - starttime,4), " seconds")

    # update scrollregion 100ms after mainloop start
    root.after(100, lambda:C.config(scrollregion=C.bbox("all")))
    mainloop()


root = Tk()
root.geometry("%dx%d+%d+%d" % (625,600,100,50))
main_frame()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...