代码之家  ›  专栏  ›  技术社区  ›  detly FBruynbroeck

PyGTK小部件的就地替换

  •  3
  • detly FBruynbroeck  · 技术社区  · 14 年前

    下面的代码创建了一列三个标签。我想取中间的标签,用另一个使用标签文本的小部件替换它

    我的实际用例是采用GTKBuilder填充的UI,并用 dynamically wrapped label 在运行时(我在这里使用了一个按钮,因为它很简单但很独特。)然后我仍然可以使用Glade来设置UI,包括标签,如果我以后想做一个标签包装,就不用在Python代码中添加错误的标签和字符串。

    目前的代码不起作用-new按钮被添加到列的末尾,我希望它保持在中间,在那里 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()
    
    4 回复  |  直到 7 年前
        1
  •  3
  •   John    14 年前

    不用把标签直接放在主容器里,你可以把每个标签放在它自己的盒子里。

    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)
    

    对此:

    box1 = gtk.HBox()
    label1 = gtk.Label("Label 1")
    box1.pack_start(label1)
    
    box2 = gtk.HBox()
    label2 = gtk.Label("Label 2")
    box2.pack_start(label2)
    
    box3 = gtk.HBox()
    label3 = gtk.Label("Label 3")
    box3.pack_start(label3)
    
    box.pack_start(box1)
    box.pack_start(box2)
    box.pack_start(box3)
    

    其余的代码可以保持不变。 您只需确保在这些框中一次只有一个子部件。

        2
  •  7
  •   Community THelper    7 年前

    我在密码里找到了解决办法 界面设计师。

    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)
    

    关键似乎是在运行之后将子属性从旧的小部件转移到新的小部件 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()
    

    为了解决你原来的问题,我用 label_set_autowrap() from here

        3
  •  0
  •   Jon    14 年前

    pygtk文档中有一些关于 add

    此方法通常用于 简单的容器,比如gtk.Window, 框架,或gtk按钮 孩子们,比如gtk.Box或gtk.Table, 此函数将选择默认值 可能不适用的填料参数 对的。

    对于包含多个子项的容器,还可以说它们具有添加项的专门功能。就你而言, gtk.Box 有三个选项: pack_start , pack_end ,和 reorder_child .

    我不知道它将如何处理使用包开始(或包结束)后,一个项目已被删除。如果做不到这一点,重新安排孩子的顺序听起来可能会有所帮助。

    如果这些都不起作用,您可以使用pack\u start以正确的顺序删除并重新添加所有小部件。

        4
  •  0
  •   Dima Tisnek    12 年前

    与Matthias的回答类似,我曾经写过下面的代码:

    它并没有保留所有的属性,因此它只适用于一些容器,那些我当时想测试的容器。

    def replace_widget(cur, replace):
      """replace cur widget with another in a container keeping child properties"""
      con = cur.get_parent()
      pos = con.child_get_property(cur, "position")
      pak = con.query_child_packing(cur)
      con.remove(cur)
      if replace.get_parent(): replace.get_parent().remove(replace)
      con.add_with_properties(replace, "position", pos)
      con.set_child_packing(replace, *pak)