Почему tk.Кнопка.configure после tkFileDialog.askopenfilename вступает в силу только после того, как метод оставлен?

#python #tkinter

#python #tkinter

Вопрос:

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

Вызываемая кнопка select_master_button привязана к команде SelectMaster .

В SelectMaster методе configure инструкция button помещается непосредственно после tkFileDialog.askopenfilename вызова.

Идея состоит в том, чтобы изменить описание кнопки и рельеф, чтобы пользователь знал об операции обработки.

Однако, когда пользователь выбирает файл и покидает диалоговое окно file, конфигурация кнопки не изменяется, и только после завершения всего метода конфигурация кнопки вступает в силу.

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

Почему tk.Button.configure after tkFileDialog.askopenfilename вступает в силу только после того, как метод оставлен?

Я на Python 2.7.

Я понимаю, что размещение инструкции button configure перед диалогом file обеспечило бы исправление, но я все еще хотел бы понять текущее поведение.

 # -*- coding: utf-8 -*-

import Tkinter as tk
import tkFileDialog
import tkMessageBox
from openpyxl import Workbook, load_workbook

class MyApp():
    def __init__(self, parent):
            self.sort_tick_value = tk.IntVar()
            self.sort_tick_value.set(1)

            ### GUI ###

            self.myParent = parent
            self.myParent.geometry("400x400")

            self.myContainer = tk.Frame(parent)
            self.myContainer.pack(expand=tk.YES, fill=tk.BOTH, padx=10, pady=5,
                                  ipadx=5, ipady=5)

            self.sort_selection_frame = tk.Frame(self.myContainer)
            self.sort_selection_frame.pack(side=tk.TOP, expand=tk.NO, fill=tk.BOTH,
                                           pady=10)

            self.select_master_frame = tk.Frame(self.myContainer)
            self.select_master_frame.pack(side=tk.TOP, expand=tk.NO, fill=tk.BOTH,
                                          pady=10)

            #### Tick Box ####

            self.sort_tick_box =tk.Checkbutton(self.sort_selection_frame,
                                               text="Sort in groups",
                                               variable=self.sort_tick_value)
            self.sort_tick_box.pack(side=tk.TOP, anchor=tk.W)

            #### Choose Master File Button ####

            self.select_master_button =  tk.Button(self.select_master_frame)
            self.select_master_button.configure(text="Select master file - "
                                                     ".xlsxn(optional)",
                                                     command=self.SelectMaster)
            self.select_master_button.pack(side = tk.TOP, anchor=tk.N)

    def SelectMaster(self):
        selected_master = tkFileDialog.askopenfilename(
                parent=root, title='Choose the master file', initialdir = 'D:/')

        self.select_master_button.configure(text="Select master file - "
                                                 ".xlsxn(scanning file, "
                                                 "please wait)", relief=tk.SUNKEN)

        print "Scanning the selected master file ..."

        wb = load_workbook(selected_master, read_only=True)
        ws = wb.active

        while …:
          # time consuming calculation ...

        self.select_master_button.configure(text="Select master filen(active)",
                                            relief=tk.RAISED)

root = tk.Tk()
root.wm_title("Title“)
myApp = MyApp(root)

root.mainloop()
  

Комментарии:

1. так работают все графические интерфейсы. mainloop вызывает множество функций по порядку — сначала получает событие мыши / клавиатуры, затем отправляет его виджету, они вызывают вашу функцию и т.д., И в конце mainloop перерисовывает виджеты (если это необходимо). Вы можете использовать root.update() , чтобы заставить mainloop перерисовывать виджеты.

2. Если вы хотите принудительно обновить отображение как можно скорее, вызовите root.update_idletasks() сразу после вашего self.select_master_button.configure() вызова. Примечание: update_idletasks() это один из многих универсальных методов виджета .

3. @furas @martineau Спасибо вам обоим за объяснение основного цикла и подсказку с root.update_idletasks(), которая, кстати, отлично работает! 🙂 Я понимаю, что self.select_master_button.configure() действие до tkFileDialog.askopenfilename без обновления, но не после, связано с тем, что FiledDialog открывает другой фрейм и заставляет другие виджеты ждать обновления в режиме ожидания.