如何让Python窗口始终处于最上层?
我在用Python写一个小程序,这个程序会打开一个小窗口,需要让这个窗口始终在其他窗口的上面。我觉得这个功能和操作系统有关,在GNU-Linux的GNOME环境下应该怎么做呢?
[更新 - Windows的解决方案]
太好了,我想我搞定了。我在Vista 64位系统上使用Python 2.5.4和Pygame 1.9.1,使用的是Eclipse。所以这个解决方案是针对Windows系统的。SetWindowPos
这个函数的详细信息可以在这里找到。我会在我的解释中提到这个。
导入的库:
from ctypes import windll
然后我设置了一个变量,用来调用user32里的"SetWindowPos":
SetWindowPos = windll.user32.SetWindowPos
现在,假设我刚刚创建了一个窗口:
screen = pygame.display.set_mode((100,100), pygame.NOFRAME)
接下来的这一行是关键。这一行代码让窗口始终在其他窗口的上面。
SetWindowPos(pygame.display.get_wm_info()['window'], -1, x, y, 0, 0, 0x0001)
基本上,你需要提供hWnd
(窗口句柄),这个句柄是通过调用display.get_wm_info()
得到的窗口ID。这样,函数就可以修改你刚刚初始化的窗口了。
-1
就是我们的hWndInsertAfter
。
MSDN网站上说:
要将一个窗口设置为最上层窗口,可以将hWndInsertAfter参数设置为HWND_TOPMOST,并确保没有设置SWP_NOZORDER标志,或者通过在Z顺序中设置窗口的位置,使其位于任何现有的最上层窗口之上。当一个非最上层窗口被设置为最上层时,它所拥有的窗口也会被设置为最上层。但它的拥有者不会改变。
所以,-1
确保这个窗口在任何其他现有的最上层窗口之上,但这可能并不总是有效。也许-2
会比-1
更有效?目前对我来说是有效的。:)
x
和y
指定了窗口的新坐标。我希望窗口在调用SetWindowPos
函数时保持在当前的位置。可惜我找不到简单的方法把当前窗口的(x,y)位置传递给这个函数。我找到了一种变通方法,但我觉得不应该在这个问题中引入新话题。
0, 0,
本来是用来指定窗口的新宽度和高度(以像素为单位)。不过,这个功能已经在你的pygame.display.set_mode()
函数中实现了,所以我把它们留在了0。0x0001
会忽略这些参数。
0x0001
对应于SWP_NOSIZE,是我唯一的uFlag。所有可用的uFlags的列表可以在提供的文档页面上找到。它们的一些十六进制表示如下:
- SWP_NOSIZE = 0x0001
- SWP_NOMOVE = 0x0002
- SWP_NOZORDER = 0x0004
- SWP_NOREDRAW = 0x0008
- SWP_NOACTIVATE = 0x0010
- SWP_FRAMECHANGED = 0x0020
- SWP_SHOWWINDOW = 0x0040
- SWP_HIDEWINDOW = 0x0080
- SWP_NOCOPYBITS = 0x0100
- SWP_NOOWNERZORDER = 0x0200
- SWP_NOSENDCHANGING = 0x0400
就这些了!希望对你有用!
感谢John Popplewell的帮助,邮箱是john@johnnypops.demon.co.uk。
3 个回答
我在尝试解决一个类似的问题时,发现了这个使用Pmw模块的解决方案。
http://www.java2s.com/Code/Python/GUI-Pmw/Showglobalmodaldialog.htm
我其实对Python了解不多,但我在网上搜索“pygtk总在最上面”时找到了这个:
http://www.mail-archive.com/pygtk@daa.com.au/msg01370.html
那里的解决方案是:
transient.set_transient_for(main_window)
你也可以试着搜索“x11总在最上面”之类的东西。这个背后的概念是,你在给窗口管理器一个“提示”,让它知道这个窗口应该保持在其他窗口的上面。不过,窗口管理器有自己的决定权,可以随意处理。
我还看到过在使用像Fluxbox这样的窗口管理器时,有层的概念,所以也许可以通过改变窗口出现的层级来解决这个问题。