Tkinter挂在快速重复的Dialog上

时间:2016-11-17 23:33:36

标签: python user-interface tkinter tk hang

问题

当我按住Return键重复打开一个Dialog时,程序 最终挂起对话框打开。什么都不是可点击的,也没有键盘 快捷方式有效。如果我通过单击离开不聚焦窗口,然后单击返回 它,挂起了。

当我按住Shift-Return重复打开CustomDialog时,程序不会挂起。

问题

  • 为什么Dialog课程在快速重复打开时有时会使程序挂起?
  • 为什么继承自CustomDialog并且只覆盖一行的Dialog类不会遇到此问题?

观察

  • 挂起不会持续发生。当它发生时更可靠 我同时运行一个cpu密集型命令,例如cat /dev/urandom
  • 单击“打开对话框”按钮(而不是按Return键)不会 似乎导致程序挂起。这可能是因为鼠标不能 单击按钮可以快速单击按钮 MainWindow.open_dialog()

示例代码

下面的代码创建了一个带有两个按钮的Tk窗口:

  • '打开对话框'打开tkinter.simpledialog.Dialog
  • 的实例
  • '打开自定义对话框'打开CustomDialog的实例,该实例继承 来自tkinter.simpledialog.Dialog,但注释了一行(line 215) ok()方法。
  • 返回键绑定到“打开对话框”按钮。
  • Shift + Return绑定到“打开自定义对话框”按钮。
  • 设定:
    • 使用Python 3.5.2运行以下代码。
    • 按住Return键。

hangingdialog.py

import tkinter
from tkinter import ttk
from tkinter.simpledialog import Dialog


class MainWindow:

    def __init__(self):
        self.root = tkinter.Tk()

        self.btn_dialog = ttk.Button(
            self.root,
            text="Open Dialog",
            command=self.open_dialog,
        )

        self.btn_custom_dialog = ttk.Button(
            self.root,
            text="Open Custom Dialog",
            command=self.open_custom_dialog,
        )

        self.btn_dialog.pack()
        self.btn_custom_dialog.pack()

        self.root.bind('<Return>', self.open_dialog)
        self.root.bind('<Shift-Return>', self.open_custom_dialog)

        self.root.mainloop()

    def open_dialog(self, event=None):
        u = Dialog(self.root, 'Dialog')
        print('Dialog Opened.')

    def open_custom_dialog(self, event=None):
        u = CustomDialog(self.root, 'Custom Dialog')
        print('Custom Dialog Opened.')


class CustomDialog(Dialog):
    """This class is identical to is identical to
    tkinter.simpledialog.Dialog, but with
    'self.withdraw()' commented out in the self.ok()
    method.
    """

    def __init__(self, parent, title=None):
        tkinter.simpledialog.Dialog.__init__(self, parent, title)

    def ok(self, event=None):
        """This method is identical to
        tkinter.simpledialog.Dialog.ok(),
        but with 'self.withdraw()' commented out.
        """
        if not self.validate():
            self.initial_focus.focus_set() # put focus back
            return

        # Using self.withdraw() here causes the
        # ui to freeze until the window loses and regains
        # focus.
        #self.withdraw()
        self.update_idletasks()

        try:
            self.apply()
        finally:
            self.cancel()


if __name__ == '__main__':
    MainWindow()

0 个答案:

没有答案