PyGTK小部件的就地替换

det*_*tly 3 python pygtk

下面的代码创建一个包含三个标签的列.我想采用中间标签,并在初始创建UI后使用标签中的文本将其替换为另一个小部件.

我的实际用例是使用GTKBuilder填充的UI,并在运行时用动态包装的标签替换任何特定的命名标签.(我在这里使用了一个按钮,因为它很简单但很独特.)然后我仍然可以使用Glade设置UI,包括标签,如果我以后想要制作标签包装,不要用我的Python代码加错标签和字符串.

现在的代码不起作用 - 新的按钮被添加到列的末尾,我希望它保持在中间,从那里label2开始.我能做些什么,最好是在哪里wrap_in_button,以确保它最终到达正确的位置?我宁愿保持一般,因为父母可能是一个Box或一个Table或任何将军Container.

import pygtk
import gtk

def destroy(widget, data=None):
    gtk.main_quit()

def wrap_in_button(label):
    text = label.get_text()
    button = gtk.Button(text)

    parent = label.get_parent()

    if parent:
        parent.remove(label)
        parent.add(button)

def Main():
    # Pretend that this chunk is actually replaced by GTKBuilder work
    # From here...
    window = gtk.Window()
    window.connect('destroy', destroy)

    box = gtk.VBox()
    window.add(box)

    label1 = gtk.Label("Label 1")
    label2 = gtk.Label("Label 2")
    label3 = gtk.Label("Label 3")

    box.pack_start(label1)
    box.pack_start(label2)
    box.pack_start(label3)

    # ...up to here

    # Comment this to see the original layout
    wrap_in_button(label2)

    window.show_all()

    gtk.main()

if __name__ == "__main__":
    Main()
Run Code Online (Sandbox Code Playgroud)

Mat*_*ias 5

我在gazpacho界面设计器的代码中找到了解决方案.

你可以使用这个功能:

def replace_widget(current, new):
    """
    Replace one widget with another.
    'current' has to be inside a container (e.g. gtk.VBox).
    """
    container = current.parent
    assert container # is "current" inside a container widget?

    # stolen from gazpacho code (widgets/base/base.py):
    props = {}
    for pspec in gtk.container_class_list_child_properties(container):
        props[pspec.name] = container.child_get_property(current, pspec.name)

    gtk.Container.remove(container, current)
    container.add(new)

    for name, value in props.items():
        container.child_set_property(new, name, value)
Run Code Online (Sandbox Code Playgroud)

关键似乎是在运行后将子属性从旧窗口小部件转移到新窗口小部件gtk.Container.add().

应用于您的示例,这将是:

import pygtk
import gtk

def replace_widget(current, new):
    """
    Replace one widget with another.
    'current' has to be inside a container (e.g. gtk.VBox).
    """
    container = current.parent
    assert container # is "current" inside a container widget?

    # stolen from gazpacho code (widgets/base/base.py):
    props = {}
    for pspec in gtk.container_class_list_child_properties(container):
        props[pspec.name] = container.child_get_property(current, pspec.name)

    gtk.Container.remove(container, current)
    container.add(new)

    for name, value in props.items():
        container.child_set_property(new, name, value)

def destroy(widget, data=None):
    gtk.main_quit()

def wrap_in_button(label):
    text = label.get_text()
    button = gtk.Button(text)

    replace_widget(label, button)

def Main():
    # Pretend that this chunk is actually replaced by GTKBuilder work
    # From here...
    window = gtk.Window()
    window.connect('destroy', destroy)

    box = gtk.VBox()
    window.add(box)

    label1 = gtk.Label("Label 1")
    label2 = gtk.Label("Label 2")
    label3 = gtk.Label("Label 3")

    box.pack_start(label1)
    box.pack_start(label2)
    box.pack_start(label3)

    # ...up to here

    wrap_in_button(label2)

    window.show_all()
    gtk.main()

if __name__ == "__main__":
    Main()
Run Code Online (Sandbox Code Playgroud)

这适用于使用Python 2.6.6和PyGTK 2.17.

作为原始问题的解决方案,我label_set_autowrap() 从这里开始使用它大部分时间都在工作.但是,它不是一个完美的解决方案,因为我无法正确对齐自动包装的文本.