下面的代码会创建一个包含三个标签的列。我想采用中间标签,并在初始创建UI 后使用标签中的文本将其替换为另一个小部件。
我的实际用例是使用GTKBuilder填充的UI,并在运行时用dynamically wrapped label替换任何特定的命名标签。 (我在这里使用了一个按钮,因为它很简单但很独特。)然后我仍然可以使用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()
答案 0 :(得分: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)
关键似乎是在运行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()
这适用于使用Python 2.6.6和PyGTK 2.17。
作为原始问题的解决方案,我使用了label_set_autowrap()
from here,并且大部分时间都有效。但是,它不是一个完美的解决方案,因为我无法正确对齐自动换行的文本。
答案 1 :(得分:3)
不是将标签直接放入主容器中,而是将每个标签放入自己的盒子中。
改变这个:
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)
其余代码可以保持不变。 您只需要确保一次只在这些框中有1个子窗口小部件。
答案 2 :(得分:0)
pygtk docs有关add
函数的一些有用信息:
此方法通常用于 简单的容器,如gtk.Window, gtk.Frame,或者持有的gtk.Button 单个小部件。用于布局 处理多个容器 孩子,如gtk.Box或gtk.Table, 此功能将选择默认值 包装参数可能不是 正确的。
对于具有多个子项的容器,它继续说它们具有用于添加项的专用函数。在您的情况下,gtk.Box
有三个选项:pack_start
,pack_end
和reorder_child
。
我不确定在删除项目后如何使用pack_start(或pack_end)处理它。如果失败了,reorder_child听起来可能会有所帮助。
如果这些都不起作用,您可以使用pack_start始终以正确的顺序删除并重新添加所有小部件。
答案 3 :(得分:0)
类似于马蒂亚斯的回答,我曾在下面写过一段代码:
它不会保留所有属性,因此它只适用于某些容器,那些我当时都要测试的容器。
为python 2.4.x和相同年龄的pygtk制作,可能仍然适合你。
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)