有什么办法可以在pygobject中猴子补丁Gtk.Widget方法(用于调试)

时间:2019-11-22 17:02:47

标签: gtk3 pygobject

我正在使用pygobject 3.24在python + gtk3中编写应用程序

我正在开发自定义窗口小部件,并且需要有关调用堆栈和do_get_preferred_widthdo_size_allocate等返回值的信息,以便调试我遇到的布局问题。

我正在尝试为常规Gtk小部件(例如Gtk.Box,Gtk.Paned等)修补这些方法。新方法将仅调用原始方法,但将其输入/输出打印到日志文件中,因此我可以关注布局逻辑。

我可以通过为每个子类创建子类来完成此操作,但是由于我的应用程序使用依赖于原始类的.ui文件,因此我无法安装这些打补丁的类,而仍使用模板({{1 }}不支持模板中的派生窗口小部件。在应用程序内重新创建模板逻辑需要大量的工作。

理想情况下,我可以像这样在运行中对猴子的方法进行修补:

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

运行时似乎完全没有意识到这些更改。我怀疑这是由于底层调用全部在C中造成的。在这一点上,我很想将日志消息插入到c源代码中并自己构建它,但这感觉有点过头了。

有人知道我如何完成这一猴子修补工作吗?还是轻松获得我需要的信息? (GTK调试器的信息不足)

1 个答案:

答案 0 :(得分:0)

在生产环境中是否仅出于调试目的需要它?如果是后者,则可以从特定的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()

如果需要批量修补,则可以使用this技术。