gtk3 - 有没有办法在 pygobject 中修补 Gtk.Widget 方法(用于调试)
问题描述
我正在使用 pygobject 3.24 在 python+gtk3 中编写应用程序
我正在开发自定义小部件,需要有关调用堆栈和返回值的信息do_get_preferred_width
,do_size_allocate
等等,以便调试我遇到的布局问题。
我正在尝试为常规 Gtk 小部件(如 Gtk.Box、Gtk.Paned 等)修补这些方法。新方法只会调用原始方法,但会将它们的输入/输出打印到日志文件中,这样我就可以遵循布局逻辑.
我可以通过为其中的每一个创建子类来实现这一点,但由于我的应用程序使用.ui
依赖于原始类的文件,我无法安装这些修补类并仍然使用模板(pygobject
不支持模板中的派生小部件)。在应用程序中重新创建模板逻辑需要大量工作。
理想情况下,我可以像这样动态地修补方法:
builder = Gtk.Builder.new_from_file('my-template.ui')
box = builder.get_object('my-box')
box.do_get_preferred_width = patched_do_get_preferred_width
但这似乎没有效果。如果我尝试在班级级别设置它,它也不起作用:
Gtk.Box.do_get_preferred_width = patched_do_get_preferred_width
运行时似乎完全没有意识到这些变化。我怀疑这是因为底层调用都在 C 中。此时我很想将日志消息插入到 C 源代码中并自己构建它,但这感觉有点过头了。
有谁知道我怎样才能完成这个猴子补丁?或者轻松获取我需要的信息?(GTK 调试器信息量不足)
解决方案
您是否需要在生产中仅用于调试目的?如果是后者,您可以从特定的 Gtk 小部件子类化并覆盖您感兴趣的方法。试试这个 MCVE:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
class Box(Gtk.Box):
def __init__(self, *args):
super().__init__(self, *args)
def get_allocated_width(self):
val = super().get_allocated_width()
print("val: ", val)
return val
def clicked(button, box):
print (box.get_allocated_width())
Gtk.Box = Box # make following calls to Gtk.Box return overriden version
win = Gtk.Window()
box = Gtk.Box()
win.add(box)
button = Gtk.Button("foo")
button.connect("clicked", clicked, box)
box.add(button)
win.show_all()
Gtk.main()
如果您需要批量修补,您可以使用此技术。
推荐阅读
- mysql - 创建数据库
- android - 在设置中关闭键盘选择器图标的 ADB 命令是什么?
- oracle - 将逻辑实体的名称更改为标题大小写 (Oracle SDDM)
- python - 在普通 Python 中找到最小的浮点数
- javascript - 参数太多的函数。如何使用和调用对象字面量作为参数
- javascript - 如何导出一个类的单个实例并在多个文件中导入同一个实例?
- ffmpeg - 为什么在 libavfilter 中存在 vaapi 过滤器,但在我编译的 ffmpeg 版本中不存在?
- typescript - 在另一个 Observable 的数组项中映射一个 Observable,将结果展平
- python - 无法导入 pytrends?
- android - Java 8+ API 对纯 kotlin 模块的脱糖支持