Команда кнопки Python 3 Tkinter не работает (очень специфический сценарий) - PullRequest
0 голосов
/ 10 декабря 2018

Я использую эти модули календаря, найденные в этом посте для моей программы, с некоторыми небольшими изменениями в импорте, чтобы он работал для последней версии Python.

Я простопокажите фрагменты моего кода, которые, по моему мнению, имеют значение для этой проблемы.

Итак, у меня есть всплывающее окно, которое я сделал, которое я использую для оповещений:

#class for pop-up windows for alerts, errors etc.
class PopUpAlert():
    def __init__(self, alert='Alert!'):
        self.root = tk.Tk()

        tk.Label(self.root,
            text=alert,
            font="Verdana 15",
            fg='red',
            padx=10,
            pady=5).pack(side=tk.TOP)

        self.root.bind('<Return>', (lambda event: self.ok()))
        tk.Button(self.root,
            text='ok',
            pady=10,
            command=self.ok).pack(side=tk.TOP)

    def ok(self):
        print('ok clicked')
        self.root.destroy()

Функция ok сделано только для того, чтобы я проверил, вызывается ли эта функция.Это окно прекрасно работает в моем коде, за исключением случаев, когда я пытаюсь реализовать его с помощью календаря, когда кнопка «ОК» моего PopUpAlert (который должен разрушить окно) перестает работать:

class CalendarDialog(tkSimpleDialog.Dialog):
    """Dialog box that displays a calendar and returns the selected date"""
    def body(self, master):
        self.calendar = ttkcalendar.Calendar(master)
        self.calendar.pack()

    def apply(self):
        self.result = self.calendar.selection

    def validate(self):
        if self.calendar.selection == None:
            PopUpAlert(alert='Please select a date or click cancel!')
            return False
        return True

В календаре есть кнопка «ОК», которая используется для подтверждения выбора даты и закрытия окна календаря.Я пытался сделать так, чтобы пользователь не мог щелкнуть «ОК», чтобы закрыть окно, если он / она не выбрал дату.Для этого я использовал функцию validate, которая предопределена в классе tkSimpleDialog.Dialog, от которого наследуется мой CalendarDialog.Я переписал функцию в своем классе CalendarDialog для вызова PopUpAlert, затем вернул False родительской функции ok (которая вызывается при нажатии кнопки «ОК» в окне календаря):

    def ok(self, event=None):

        if not self.validate():
            self.initial_focus.focus_set() # put focus back
            return

        self.withdraw()
        self.update_idletasks()

        self.apply()

        self.cancel()

    def cancel(self, event=None):

        # put focus back to the parent window
        self.parent.focus_set()
        self.destroy()

(Все это можно найти в файле tkSimpleDialog, который связан с другой страницей SO, на которую я ссылался выше.)

После комментирования строк одна за другой я обнаружил, что "Кнопка «ОК» на моем PopUpAlert не работает, только если self.root.destroy() не вызывается в календаре.Зачем?Как это исправить?

Я уже пытался изменить PopUpAlert на окно Toplevel, которое также не работало.

1 Ответ

0 голосов
/ 10 декабря 2018

Было бы намного лучше, если бы вы предоставили mcve вместо того, чтобы просить нас сделать это.

Проблема в том, что диалоговое окно по умолчанию отключает щелчки в других окнах, включая те, которые появляются в нем.Чтобы это исправить, вам нужно использовать Toplevel вместо Tk (как уже упоминалось) AND и добавить эту строку кода в конец PopUpAlert.__init__:

self.root.grab_set() 

Было бы намного аккуратнее, если бы вы подклассифицировали Toplevel, а не эту странную оболочку.Вот mcve:

try:
    import Tkinter as tk
    import tkSimpleDialog as sd
except:
    import tkinter as tk
    from tkinter import simpledialog as sd

#class for pop-up windows for alerts, errors etc.
class PopUpAlert(tk.Toplevel):
    def __init__(self, master, alert='Alert!', **kwargs):
        tk.Toplevel.__init__(self, master, **kwargs)

        tk.Label(self,
            text=alert,
            font="Verdana 15",
            fg='red',
            padx=10,
            pady=5).pack(side=tk.TOP)

        self.bind('<Return>', self.ok)
        tk.Button(self,
            text='ok',
            pady=10,
            command=self.ok).pack(side=tk.TOP)

        self.grab_set() # this window only gets commands

    def ok(self, *args):
        print('ok clicked')
        self.destroy()

class CalendarDialog(sd.Dialog):
    """Dialog box that displays a calendar and returns the selected date"""
    def body(self, master):
        self.calendar = tk.Label(master, text="Whatever you do, don't click 'OK'!")
        self.calendar.pack()

    def validate(self):
        PopUpAlert(self, alert='Please select a date or click cancel!')

def display():
    CalendarDialog(root)

root = tk.Tk()
tk.Button(root, text='data data data', command=display).pack()
root.mainloop()

Заметьте, я также избавился от той бесполезной лямбды, которая, как оказалось, моя любимая мозоль.lambda отлично в некоторых случаях, но это очень редко нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...