强制设置tkinter窗口始终具有焦点

时间:2015-08-10 18:50:20

标签: python python-2.7 tkinter

有没有办法告诉Tkinter我想要一些小部件始终保持专注?我创建了一个可以运行以显示我的问题的最小示例,这是一个示例窗口,其中还覆盖了小的顶层窗口:

enter image description here

现在,如果我点击上方标题 tk ,主窗口就会聚焦,突然小窗口后面主窗口

enter image description here

我希望将这些较小的窗口视为始终对焦,直到用户专门关闭它们为止。当然这是一个最小的例子,这是我的大型应用程序的一个小部分背后的想法,是否有任何简单的设置我可以用于顶层,以确保它将始终保持焦点,无论其他窗口?以下是可以运行以复制此代码的实际代码:

from Tkinter import *

class PropertyDialog(Toplevel):
    def __init__(self, root, string):
        Toplevel.__init__(self)
        self.wm_overrideredirect(1)
        self.root = root 
        self.\
             geometry('+%d+%d' %
                      (root.winfo_pointerx(),
                       root.winfo_pointery()))
        try:
            self.tk.call('::Tk::unsupported::MacWindowStyle',
                                         'style', self._w,
                                         'help', 'noActivates')
        except TclError:
            pass
        window_frame = Frame(self)
        window_frame.pack(side=TOP, fill=BOTH, expand=True)
        exit_frame = Frame(window_frame, background='#ffffe0')
        exit_frame.pack(side=TOP, fill=X, expand=True)
        button = Button(exit_frame, text='x', width=3, command=self.free,
               background='#ffffe0', highlightthickness=0, relief=FLAT)
        button.pack(side=RIGHT)
        text_frame = Frame(window_frame)
        text_frame.pack(side=TOP, fill=BOTH, expand=True)
        label = Label(text_frame, text=string, justify=LEFT,
                      background='#ffffe0',
                      font=('tahoma', '8', 'normal'))
        label.pack(ipadx=1)

    def free(self):
        self.destroy() # first we destroy this one
        for val,widget in enumerate(dialogs): # go through the dialogs list
            if widget is self: # when we find this widget
                dialogs.pop(val) # pop it out
                break # and stop searching
        if dialogs: # if there are any dialogs left:
            for widget in dialogs: # go through each widget
                widget.lift(aboveThis=self.root) # and lift it above the root

def bind():
    """
    toggle property window creation mode
    """
    root.bind('<ButtonPress-1>', create)


def create(event):
    """
    Create actual window upon mouse click
    """
    dialogs.append(PropertyDialog(root, 'help me'))

root = Tk()
dialogs = []
root.geometry('%dx%d' % (300,400))

Button(root, text='create', command=bind).pack()

root.mainloop()

2 个答案:

答案 0 :(得分:1)

改变这个:

    if dialogs: # if there are any dialogs left:
        for widget in dialogs: # go through each widget
            widget.lift(aboveThis=self.root) # and lift it above the root

到此:

    if dialogs: # if there are any dialogs left:
        for widget in dialogs: # go through each widget
            widget.lift() # and lift it above the root

小部件将保持在主窗口之上。

编辑:

很抱歉,只有一半工作......寡妇有时会使用该代码

: - X

在你关闭其中一个之前,小部件保持在最顶层....这段代码确实将小部件保持在最顶层

它在您生成窗口时使用self.attributes("-topmost", True)

再次抱歉。

from Tkinter import *

class PropertyDialog(Toplevel):
    def __init__(self, root, string):
        Toplevel.__init__(self)
        self.wm_overrideredirect(1)
        self.root = root 
        self.\
             geometry('+%d+%d' %
                      (root.winfo_pointerx(),
                       root.winfo_pointery()))
        try:
            self.tk.call('::Tk::unsupported::MacWindowStyle',
                                         'style', self._w,
                                         'help', 'noActivates')
        except TclError:
            pass
        window_frame = Frame(self)
        window_frame.pack(side=TOP, fill=BOTH, expand=True)
        exit_frame = Frame(window_frame, background='#ffffe0')
        exit_frame.pack(side=TOP, fill=X, expand=True)
        button = Button(exit_frame, text='x', width=3, command=self.free,
               background='#ffffe0', highlightthickness=0, relief=FLAT)
        button.pack(side=RIGHT)
        text_frame = Frame(window_frame)
        text_frame.pack(side=TOP, fill=BOTH, expand=True)
        label = Label(text_frame, text=string, justify=LEFT,
                      background='#ffffe0',
                      font=('tahoma', '8', 'normal'))
        label.pack(ipadx=1)
        self.attributes("-topmost", True)

    def free(self):
        self.destroy() # first we destroy this one

def bind():
    """
    toggle property window creation mode
    """
    root.bind('<ButtonPress-1>', create)


def create(event):
    """
    Create actual window upon mouse click
    """
    dialogs.append(PropertyDialog(root, 'help me'))

root = Tk()
dialogs = []
root.geometry('%dx%d' % (300,400))

Button(root, text='create', command=bind).pack()

root.mainloop()

答案 1 :(得分:0)

我建议远离Toplevel窗口小部件,因为这些窗口是单独的窗口,你正在抑制它们的窗口行为。此版本使用PropertyDialog几何管理器使Frame继承自Toplevel而非place()。单击主窗口时,它首先检查单击的窗口小部件是主窗口还是弹出窗口,以防止在关闭现有窗口时出现新的弹出窗口。更改的区域标有#CHANGED#

from Tkinter import *

class PropertyDialog(Frame): #CHANGED#
    def __init__(self, root, string, event): #CHANGED#
        Frame.__init__(self) #CHANGED#
        self.root = root 
        try:
            self.tk.call('::Tk::unsupported::MacWindowStyle',
                                         'style', self._w,
                                         'help', 'noActivates')
        except TclError:
            pass
        exit_frame = Frame(self, background='#ffffe0') #CHANGED#
        exit_frame.pack(side=TOP, fill=X, expand=True)
        button = Button(exit_frame, text='x', width=3, command=self.free,
               background='#ffffe0', highlightthickness=0, relief=FLAT)
        button.pack(side=RIGHT)
        text_frame = Frame(self) #CHANGED#
        text_frame.pack(side=TOP, fill=BOTH, expand=True)
        label = Label(text_frame, text=string, justify=LEFT,
                      background='#ffffe0',
                      font=('tahoma', '8', 'normal'))
        label.pack(ipadx=1)
        self.place(x=event.x, y=event.y, anchor=NW) #CHANGED#

    def free(self):
        self.destroy()
        # other things you want to do - if there's nothing else,
        # just bind the close button to self.destroy

def bind():
    """
    toggle property window creation mode
    """
    root.bind('<ButtonPress-1>', create)


def create(event):
    """
    Create actual window upon mouse click
    """
    if event.widget is root: #CHANGED#
        dialogs.append(PropertyDialog(root, 'help me', event))

root = Tk()
dialogs = []
root.geometry('%dx%d' % (300,400))

Button(root, text='create', command=bind).pack()

root.mainloop()