tkinter.simpledialog. Диалог оставляет инициатора tkinter.Button в депрессии

Я использую Python 3.3 на Windows 7. У меня есть tkinter приложение, где один Button разжигает tkinter.simpledialog.Dialog, Вот так (это полный, работающий пример):

import tkinter
import tkinter.simpledialog

class Mainframe(tkinter.Frame):
    def __init__(self, parent):
        super(Mainframe, self).__init__(parent)
        self.parent = parent
        self.button = tkinter.Button(self, text="Open Dialog")
        open_dialog_op = lambda ev: self.open_dialog(ev)
        self.button.bind("<Button-1>", open_dialog_op)
        self.button.bind("<Return>", open_dialog_op)
        self.button.pack(side=tkinter.LEFT)

    def open_dialog(self, event):
        dialog = tkinter.simpledialog.Dialog(self.parent, "My Dialog")
        self.button.config(relief=tkinter.RAISED)  # does not help!

root = tkinter.Tk()
Mainframe(root).pack()
root.mainloop()

Поведение:

  • если вы сосредоточены на "Открытый диалог" Button и наберите RETURN, все работает хорошо
  • если щелкнуть мышью Button, диалог появляется все хорошо, но
  • когда диалог закрывается, "Открыть диалог" Button показано в депрессивном состоянии (tkinter.SUNKENесли я не ошибаюсь?) гос.
  • (Интересно, что когда диалог открыт, Button отображается нормально. Подавленный вид начинается только после закрытия диалога.)
  • Я попытался исправить проблему, просто позвонив button.config(relief=tkinter.RAISED), но это, похоже, ничего не делает в этом случае.

(На самом деле мое полное приложение начинает показывать кнопку как нажатую сразу после ее нажатия, а не только после того, как диалоговое окно снова закрывается. Я нахожу это намного более логичным: simpledialog локальный цикл событий захватывает все события, потому что simpledialog модально; это может включать в себя <ButtonRelease-1> событие мыши на кнопке?)

Вопросы:

  1. Почему это происходит?
  2. Почему поведение в моем полном приложении может отличаться?
  3. Как я могу избежать или восстановить оба?

2 ответа

Решение

Это происходит потому, что вы частично перекрываете привязки по умолчанию, которые делают правильно.

Если вы хотите, чтобы кнопка выполняла функцию при активации кнопки, правильный способ сделать это - добавить command вариант с кнопкой. Причина, по которой я использую "активацию" вместо "нажатие", заключается в том, что, как показывает ваш код, существует несколько способов активировать кнопку в ТК: нажатия кнопок, возвратные нажатия, нажатия клавиш ускорения и т. Д.

Код, который вы написали, не заменяет довольно большой набор привязок по умолчанию. Ответ от iCodez правильно исправляет наиболее очевидные дефекты, но оставляя привязки по умолчанию в силе и используя command= будет работать для случаев, которые вы не тестировали (например, работа только с клавиатуры).

У меня есть простое, обходное решение для третьего вопроса. Собственно, у вас самого был ответ в вашем посте. Измените эту строку:

self.button.bind("<Button-1>", open_dialog_op)

к этому:

self.button.bind("<ButtonRelease-1>", open_dialog_op)

Сейчас, open_dialog_op связан с выпуском щелчка мыши. Значение simpledialog откроется только после того, как кнопка вернется вверх (каково ее поведение).

Тем не менее, я также хотел бы сделать предложение. Почему бы не использовать tkinter.messagebox.askokcancel за это? Это то же самое, что и системные подсказки Windows. Увидеть ниже:

tkinter.simpledialog.Dialog диалог:

tkinter.messagebox.askokcancel диалог:

Другие вопросы по тегам