You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gtk4 ColumnView出现Gtk-CRITICAL警告与数据更新视觉闪烁问题求助

Gtk4 ColumnView出现Gtk-CRITICAL警告与数据更新视觉闪烁问题求助

你好,我帮你排查了这两个关联问题,还发现了代码里一个小笔误,一起给你梳理清楚~

问题根源分析

  1. Gtk-CRITICAL警告:你给ScrolledWindow设置了set_propagate_natural_width(True)和set_propagate_natural_height(True),这会让ScrolledWindow强制继承子控件(ColumnView)的自然尺寸,直接干扰了Gtk内部调整器(Adjustment)的正常计算逻辑,导致lower + page_size <= upper这个断言条件不成立,从而反复抛出警告。
  2. 视觉Glitch:同样是ScrolledWindow的尺寸传播设置冲突,当你更新TestItem的value时,ColumnView的单元格重绘被布局矛盾打断,出现显示异常;而鼠标 hover 时触发了局部重绘,才临时修复了显示问题。
  3. 额外小问题:代码里的“清空列表”按钮被后面的“增加”按钮变量覆盖了,导致清空按钮根本没显示在界面上,这个我也一起帮你修正了。

解决方案

  • 移除ScrolledWindow中set_propagate_natural_width(True)和set_propagate_natural_height(True)这两个设置,让ScrolledWindow自己管理视口尺寸,避免干扰调整器计算;
  • 修复按钮变量覆盖的问题,确保两个功能按钮都能正常显示和工作。

修改后的完整代码

#!/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_btn = Gtk.Button.new_from_icon_name('edit-clear')
        clear_btn.connect("clicked", self.clear)
        buttons.append(clear_btn)
        increase_btn = Gtk.Button.new_from_icon_name('list-add')
        increase_btn.connect("clicked", self.increase)
        buttons.append(increase_btn)
        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_adjustment_configure的CRITICAL警告;
  • 点击“increase”按钮时,value列的数值会立即正确重绘,不会出现视觉闪烁;
  • 清空按钮也能正常显示并工作。

备注:内容来源于stack exchange,提问作者Kilobug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:03:15