XRANDR中CARD变量类型是什么?Python-Xlib调用set_screen_size报错求助
问题:Python-Xlib调用randr.set_screen_size()报struct.error错误
我正在开发一个用Python-Xlib操控显示器的程序,其他功能正常,但调用randr.set_screen_size()时遇到问题。该函数需要三个参数:窗口变量、两个CARD16类型的宽高参数。查XRANDR文档只看到CARD32、CARD16、CARD8类型的列举,但没说明定义和生成方式。
最初传入整数时报错struct.error: required argument is not an integer,试了字符串、bin生成的二进制也一样。
Edit1:尝试转换为16位无符号整数仍无效
了解到CARD16是16位无符号短整数,参考资料说Python-Xlib用struct处理这类类型,于是尝试提前转成16位无符号整数,代码如下:
import struct from Xlib import X, display, Xutil from Xlib.ext import randr d = display.Display(':0') screen = 0 info = d.screen(screen) window = info.root short16bit = struct.pack("H", int(2000)) randr.set_screen_size(window, short16bit, short16bit)
错误信息:
Traceback (most recent call last): File "/home/deishuukaikirpi/XRANDRTesting.py", line 59, in <module> randr.set_screen_size(window, short16bit, short16bit) File "/home/deishuukaikirpi/.local/lib/python3.9/site-packages/Xlib/ext/randr.py", line 387, in set_screen_size return SetScreenSize( File "/home/deishuukaikirpi/.local/lib/python3.9/site-packages/Xlib/protocol/rq.py", line 1347, in __init__ self._binary = self._request.to_binary(*args, **keys) File "/home/deishuukaikirpi/.local/lib/python3.9/site-packages/Xlib/protocol/rq.py", line 1069, in to_binary static_part = struct.pack(self.static_codes, *pack_items) struct.error: required argument is not an integer
传入大整数时会报struct.error: ushort format requires 0 <= number <= (0x7fff * 2 + 1),说明确实是要求无符号短整数,但就是报错。
Edit2:确认最初传入的是整数
原始代码直接传整数也报同样错误:
import struct from Xlib import X, display, Xutil from Xlib.ext import randr d = display.Display(':0') screen = 0 info = d.screen(screen) window = info.root randr.set_screen_size(window, 2000, 2000)
甚至用randr.set_screen_size(window,int(2000),int(2000))强制转整数也没用。
解决方案
问题核心是根窗口未订阅RandR事件,Python-Xlib的RandR扩展函数在发送请求前需要窗口已注册接收RandR事件,否则底层协议打包时会抛出看似无关的struct.error。此外,不需要手动用struct.pack处理整数,直接传入0-65535范围内的整数即可。
修正后的代码:
from Xlib import display from Xlib.ext import randr # 连接到X服务器 d = display.Display(':0') screen = d.screen() root_window = screen.root # 关键步骤:让根窗口订阅RandR屏幕变更事件 randr.select_input(root_window, randr.RRScreenChangeNotifyMask) # 直接传入符合CARD16范围的整数 randr.set_screen_size(root_window, 2000, 2000) # 同步请求,确保命令生效 d.sync()
错误原因解析
- 未订阅RandR事件:RandR扩展要求操作窗口必须先订阅相关事件,否则请求打包时会出现参数异常,表现为
struct.error而非直接提示未订阅。 - 错误使用struct.pack:
struct.pack生成的是字节串,而set_screen_size需要的是整数类型,手动打包反而导致类型不匹配,加重错误。
内容的提问来源于stack exchange,提问作者Lazuli
相关产品推荐
相关产品推荐

