我有一个运行一些嵌入式 Python 脚本的 MFC 应用程序。我正在尝试制作这个嵌入式脚本创建的对话框之一,但我没有取得多大成功。
谁能指出我制作模态对话框的方法?我需要为此使用 Windows 函数还是仅 Tk 或 Python 函数就足够了?
对于我在谷歌上搜索的内容,以下功能组合应该可以发挥作用,但它们似乎并没有按我预期的方式工作:
focus_set()
grab_set()
transient(parent)
我有一个运行一些嵌入式 Python 脚本的 MFC 应用程序。我正在尝试制作这个嵌入式脚本创建的对话框之一,但我没有取得多大成功。
谁能指出我制作模态对话框的方法?我需要为此使用 Windows 函数还是仅 Tk 或 Python 函数就足够了?
对于我在谷歌上搜索的内容,以下功能组合应该可以发挥作用,但它们似乎并没有按我预期的方式工作:
focus_set()
grab_set()
transient(parent)
grab_set
是使窗口“应用程序模式”的正确机制。也就是说,它从同一应用程序中的所有其他窗口(即:同一进程中的其他 Tkinter 窗口)获取所有输入,但它允许您与其他应用程序交互。
如果您希望您的对话框是全局模式的,请使用grab_set_global
. 这将接管整个系统的所有键盘和鼠标输入。使用它时你必须非常小心,因为如果你有一个错误阻止你的应用程序释放抓取,你可以很容易地将自己锁定在计算机之外。
当我需要这样做时,在开发过程中我会尝试编写一个防弹故障保护,例如一个计时器,它将在固定的时间后释放抓取。
在我的一个项目中,我在父窗口上使用了 Tcl 窗口管理器属性“-disabled”,称为(模态)顶层对话框窗口。
不知道您使用 MFC 应用程序显示的哪些窗口是由 Tcl 东西创建或使用的,但如果您的父窗口是基于 Tk 的,您可以这样做:
在 Python 中,只需在顶层窗口的创建方法中调用父窗口:
MyParentWindow.wm_attributes("-disabled", True)
在你得到你想要的模式窗口后,不要忘记在你的模式窗口中使用回调函数,再次启用父窗口上的输入!(否则您将无法再次与父窗口交互!):
MyParentWindow.wm_attributes("-disabled", False)
Tkinter(Tcl 版本 8.6)Python 示例(在 Windows 10 64 位上测试):
# Python 3+
import tkinter as tk
from tkinter import ttk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.minsize(300, 100)
self.button = ttk.Button(self, text="Call toplevel!", command=self.Create_Toplevel)
self.button.pack(side="top")
def Create_Toplevel(self):
# THE CLUE
self.wm_attributes("-disabled", True)
# Creating the toplevel dialog
self.toplevel_dialog = tk.Toplevel(self)
self.toplevel_dialog.minsize(300, 100)
# Tell the window manager, this is the child widget.
# Interesting, if you want to let the child window
# flash if user clicks onto parent
self.toplevel_dialog.transient(self)
# This is watching the window manager close button
# and uses the same callback function as the other buttons
# (you can use which ever you want, BUT REMEMBER TO ENABLE
# THE PARENT WINDOW AGAIN)
self.toplevel_dialog.protocol("WM_DELETE_WINDOW", self.Close_Toplevel)
self.toplevel_dialog_label = ttk.Label(self.toplevel_dialog, text='Do you want to enable my parent window again?')
self.toplevel_dialog_label.pack(side='top')
self.toplevel_dialog_yes_button = ttk.Button(self.toplevel_dialog, text='Yes', command=self.Close_Toplevel)
self.toplevel_dialog_yes_button.pack(side='left', fill='x', expand=True)
self.toplevel_dialog_no_button = ttk.Button(self.toplevel_dialog, text='No')
self.toplevel_dialog_no_button.pack(side='right', fill='x', expand=True)
def Close_Toplevel(self):
# IMPORTANT!
self.wm_attributes("-disabled", False) # IMPORTANT!
self.toplevel_dialog.destroy()
# Possibly not needed, used to focus parent window again
self.deiconify()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
有关 Tcl 窗口管理器属性的更多信息,请查看 Tcl 文档:https ://wiki.tcl.tk/9457