Python Xlib在导入函数中无法正常工作的问题排查
解决Python Xlib代码封装到函数后无法运行的问题
我之前把Xlib的示例代码封装到自定义函数里时也碰到过一模一样的问题,主要是几个容易忽略的细节导致的,咱们一步步来解决:
1. 先修复Xlib的导入路径问题
你把sys.path.append放在函数内部,这会导致只有当函数执行时才会添加路径,而且如果函数内的导入逻辑有问题,很容易出现找不到模块的情况。建议把路径修改和Xlib的导入放到脚本最顶部,让整个脚本运行时都能正确找到Xlib:
# Python 2/3兼容性处理 from __future__ import print_function import sys import os # 提前添加路径,放在脚本最开头 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from Xlib import X, display, Xutil def xlib_test(): print('Running xlib_test()') # 后续代码放在这里...
2. 避免函数内的Xlib资源被提前回收
当函数执行完毕后,函数内的局部变量(比如Display实例、Window对象)会被Python的垃圾回收机制清理,这时候Xlib创建的窗口、像素图这些资源会被直接销毁,导致窗口要么一闪而过,要么根本不显示。
解决方法我推荐在函数内启动事件循环,让函数一直处于阻塞状态直到窗口关闭,给你的Window类添加一个事件循环方法:
class Window(object): def __init__(self, display): self.d = display self.screen = self.d.screen() # 创建背景像素图的代码保持不变 bgsize = 20 bgpm = self.screen.root.create_pixmap( bgsize, bgsize, self.screen.root_depth ) bggc = self.screen.root.create_gc( foreground=self.screen.black_pixel, background=self.screen.black_pixel ) bgpm.fill_rectangle(bggc, 0, 0, bgsize, bgsize) bggc.change(foreground=self.screen.white_pixel) bgpm.arc(bggc, -bgsize // 2, 0, bgsize, bgsize, 0, 360 * 64) bgpm.arc(bggc, bgsize // 2, 0, bgsize, bgsize, 0, 360 * 64) bgpm.arc(bggc, 0, -bgsize // 2, bgsize, bgsize, 0, 360 * 64) bgpm.arc(bggc, 0, bgsize // 2, bgsize, bgsize, 0, 360 * 64) # 修复窗口创建的参数,补充完整的事件掩码 self.window = self.screen.root.create_window( 100, 100, 400, 300, 0, self.screen.root_depth, X.InputOutput, X.CopyFromParent, background_pixmap=bgpm, # 必须添加事件掩码才能接收窗口事件 event_mask=X.ExposureMask | X.StructureNotifyMask | X.ButtonPressMask ) # 别忘了映射窗口,不然窗口不会显示出来 self.window.map() def run(self): # 启动事件循环,保持窗口运行 while True: event = self.d.next_event() # 处理关闭窗口的事件 if event.type == X.DestroyNotify: break
然后在xlib_test函数里调用这个run方法:
def xlib_test(): print('Running xlib_test()') # 创建Display实例 d = display.Display() # 创建窗口对象 win = Window(d) # 启动事件循环,阻塞直到窗口关闭 win.run()
3. 关键细节:映射窗口与事件掩码
很多时候Xlib窗口不显示,就是因为忘了调用self.window.map()来映射窗口;另外如果没有添加合适的event_mask,窗口无法接收任何事件,看起来就像“无法正常运行”。
把这些修改整合起来,运行你的xlib_test函数,窗口应该就能正常显示并响应事件了。
内容的提问来源于stack exchange,提问作者user3208430
相关产品推荐
相关产品推荐

