简单的ColumnView组件上的警告与视觉异常

编程语言 2026-07-12

我在做一个小型的Python / Gtk4程序。布局相对简单:上方区域包含输入控件和一个“添加”按钮;接着是一个显示已添加项的ColumnView,最后是一排用于对项进行操作的按钮。

我把代码精简成一个简单的演示版本,输入只有一个名称(文本、Entry)和一个数值(整数、SpinButton),ColumnView仅有两列,且有两种操作(清空列表、将所有值增加)。

我遇到了两个问题,我怀疑它们相关,但还没找到修复方法。第一个问题是在终端窗口定期弹出的警告:

Gtk-CRITICAL **: 10:21:37.931: gtk_adjustment_configure: assertion 'lower + page_size <= upper' failed

第二个问题是在使用“增加”按钮时,数值列出现了一些视觉上的错乱(把鼠标移到它上方似乎能修复)。

发生了什么? “Gtk-CRITICAL” 警告会定期在终端显示,数据改变时也会出现可视化错乱。

应该是什么样? 终端不应出现警告,且也不应出现任何错乱。

以下是演示代码:

#!/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)

请问有谁能帮我找出解决这些问题的方法?

解决方案

这是Gtk的 bug 9316,已在版本4.21.4中修复(参见 https://gitlab.gnome.org/GNOME/gtk/-/blob/main/NEWS)。仅仅升级Gtk(我之前使用的是4.20.x版本)就解决了这个问题。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章