将控件强制置于垂直盒子的底部
我在做一个小型的Python/Gtk4程序。布局相对简单:上方有一个带输入框的区域和一个“添加”按钮,然后是一个显示已添加项的ColumnView,最后是一排用于对这些项进行操作的按钮。我希望按钮始终位于窗口底部,不论窗口大小以及中间的ColumnView的大小如何。
我尝试在ComumnView以及其中的ScrolledWindow上使用 set_valign(Gtk.Align.FILL),并在包含按钮的水平Box上使用 set_valign(Gtk.Align.END),但set_valign似乎没有任何效果。
下面是这个小演示目前的呈现效果:
下面是它应该呈现的样子:
下面是一个经过简化的演示代码,展示了同样的问题:
#!/usr/bin/python3
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, Gio, GObject, GLib
class TestItem(GObject.Object):
__gtype_name__ = "TestItem"
name = GObject.Property(type=str)
value = GObject.Property(type=int)
def __init__(self, name: str, value: int):
super().__init__()
self.name = name
self.value = value
def make_table_column(title, field):
"""
Make a column for a field
"""
template = b"""<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<binding name="label">
<lookup name="%s" type="TestItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
""" % (field.encode('ascii'),)
template = GLib.Bytes.new(template)
factory = Gtk.BuilderListItemFactory.new_from_bytes(None, template)
col = Gtk.ColumnViewColumn(title = title, factory = factory,
resizable = True)
return col
class Test(Gtk.ApplicationWindow):
def __init__(self, **kargs):
super().__init__(**kargs, title="Test")
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
control = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
control.append(Gtk.Label(label = "Name:"))
self.name = Gtk.Entry()
control.append(self.name)
control.append(Gtk.Label(label = "Value:"))
self.value = Gtk.SpinButton.new_with_range(1, 100, 1)
control.append(self.value)
button = Gtk.Button.new_from_icon_name('list-add')
button.connect("clicked", self.add)
control.append(button)
vbox.append(control)
self.model = Gio.ListStore(item_type = TestItem)
view = Gtk.ColumnView()
self.selection = Gtk.NoSelection(model = self.model)
view.set_model(self.selection)
view.append_column(make_table_column("Item name", 'name'))
view.append_column(make_table_column("Value", 'value'))
scroll = Gtk.ScrolledWindow()
scroll.set_child(view)
scroll.set_propagate_natural_width(True)
scroll.set_propagate_natural_height(True)
scroll.set_valign(Gtk.Align.FILL)
vbox.append(scroll)
buttons = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
buttons.set_valign(Gtk.Align.END)
clear = Gtk.Button.new_from_icon_name('edit-clear')
clear.connect("clicked", self.clear)
clear = Gtk.Button.new_from_icon_name('list-add')
clear.connect("clicked", self.increase)
buttons.append(clear)
vbox.append(buttons)
vbox.set_valign(Gtk.Align.FILL)
self.set_child(vbox)
self.set_default_size(600, 400)
def add(self, _widget):
name = self.name.get_buffer().get_text()
value = int(self.value.get_value())
item = TestItem(name, value)
self.model.insert(0, item)
def increase(self, _widget):
for item in self.model:
item.value += 1
def clear(self, _widget):
self.model.remove_all()
def on_activate(app):
win = Test(application=app)
win.present()
app = Gtk.Application(application_id='org.kilobug.test')
app.connect('activate', on_activate)
app.run(None)
解决方案
我从一个IRC频道得到了答案,解决方法是在对 ScrolledWindow 和 ColumnView 调用 .set_vexpand(True),而不是对 set_valign 和 set_propagate_natural_* 的调用,这样就得到了以下修正后的代码:
#!/usr/bin/python3
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, Gio, GObject, GLib
class TestItem(GObject.Object):
__gtype_name__ = "TestItem"
name = GObject.Property(type=str)
value = GObject.Property(type=int)
def __init__(self, name: str, value: int):
super().__init__()
self.name = name
self.value = value
def make_table_column(title, field):
"""
Make a column for a field
"""
template = b"""<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<binding name="label">
<lookup name="%s" type="TestItem">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
""" % (field.encode('ascii'),)
template = GLib.Bytes.new(template)
factory = Gtk.BuilderListItemFactory.new_from_bytes(None, template)
col = Gtk.ColumnViewColumn(title = title, factory = factory,
resizable = True)
return col
class Test(Gtk.ApplicationWindow):
def __init__(self, **kargs):
super().__init__(**kargs, title="Test")
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
control = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
control.append(Gtk.Label(label = "Name:"))
self.name = Gtk.Entry()
control.append(self.name)
control.append(Gtk.Label(label = "Value:"))
self.value = Gtk.SpinButton.new_with_range(1, 100, 1)
control.append(self.value)
button = Gtk.Button.new_from_icon_name('list-add')
button.connect("clicked", self.add)
control.append(button)
vbox.append(control)
self.model = Gio.ListStore(item_type = TestItem)
view = Gtk.ColumnView()
self.selection = Gtk.NoSelection(model = self.model)
view.set_model(self.selection)
view.append_column(make_table_column("Item name", 'name'))
view.append_column(make_table_column("Value", 'value'))
view.set_vexpand(True)
scroll = Gtk.ScrolledWindow()
scroll.set_child(view)
scroll.set_vexpand(True)
vbox.append(scroll)
buttons = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
clear = Gtk.Button.new_from_icon_name('edit-clear')
clear.connect("clicked", self.clear)
clear = Gtk.Button.new_from_icon_name('list-add')
clear.connect("clicked", self.increase)
buttons.append(clear)
vbox.append(buttons)
self.set_child(vbox)
self.set_default_size(600, 400)
def add(self, _widget):
name = self.name.get_buffer().get_text()
value = int(self.value.get_value())
item = TestItem(name, value)
self.model.insert(0, item)
def increase(self, _widget):
for item in self.model:
item.value += 1
def clear(self, _widget):
self.model.remove_all()
def on_activate(app):
win = Test(application=app)
win.present()
app = Gtk.Application(application_id='org.kilobug.test')
app.connect('activate', on_activate)
app.run(None)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。