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

如何用Glade和Python实现含自定义迷你窗口项的滚动列表?

实现方案与学习指引

一、Glade中完全可行

你要的这种带自定义“迷你界面”的滚动列表,用Gtk.ListBox就能实现,完全可以在Glade里完成布局设计:

  • 在Glade中先设计单个列表项的布局(比如一个Gtk.Box,里面放剩余时间标签、暂停按钮、停止按钮),可以把这个布局存为单独模板,或直接在主窗口的ListBox里作为原型。
  • 主界面的滚动区域内放置Gtk.ListBox,后续用Python代码动态生成你设计的列表项实例,添加到ListBox中即可。
    Gtk.ListBox天生支持滚动(配合Gtk.ScrolledWindow),且允许每个列表项是任意复杂的Widget组合,完全能替代你不想用的GtkTreeView。

二、Python与多定时器的交互实现

核心思路是用类封装每个定时器的UI和逻辑,让每个列表项成为独立的功能单元:

  1. 定义一个TimerItem类,继承自你在Glade中设计的列表项容器(比如Gtk.Box),在类中封装:
    • UI控件引用:剩余时间标签、暂停/停止按钮
    • 定时器状态:剩余秒数、是否运行、Gtk超时回调的ID(用于暂停/取消)
  2. 类内部实现定时器逻辑:
    • 启动定时器:用GLib.timeout_add(1000, self.update_time)注册每秒更新剩余时间的回调
    • 暂停/恢复:暂停时调用GLib.source_remove(self.timeout_id)取消回调,恢复时重新注册
    • 停止:取消回调后重置时间,并从ListBox中移除当前项
  3. 按钮信号绑定:在类的初始化方法中,把暂停/停止按钮的clicked信号连接到类内部的对应方法,这样每个列表项的按钮只会触发自身的定时器逻辑,不会互相干扰。
  4. 新增定时器:当用户在设置区输入时间并点击启动时,实例化一个TimerItem,传入设置的时间,然后调用list_box.append(timer_item)把它添加到滚动列表中。

示例代码片段(简化版):

import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, GLib

class TimerItem(Gtk.Box):
    def __init__(self, total_seconds):
        super().__init__(spacing=10)
        self.total_seconds = total_seconds
        self.remaining = total_seconds
        self.running = False
        self.timeout_id = None

        # 从Glade加载布局或者直接创建控件
        self.time_label = Gtk.Label(label=self.format_time(self.remaining))
        self.pause_btn = Gtk.Button(label="暂停")
        self.stop_btn = Gtk.Button(label="停止")

        self.append(self.time_label)
        self.append(self.pause_btn)
        self.append(self.stop_btn)

        # 绑定信号
        self.pause_btn.connect("clicked", self.on_pause_clicked)
        self.stop_btn.connect("clicked", self.on_stop_clicked)

        # 启动定时器
        self.start_timer()

    def format_time(self, seconds):
        mins = seconds // 60
        secs = seconds % 60
        return f"{mins:02d}:{secs:02d}"

    def start_timer(self):
        self.running = True
        self.timeout_id = GLib.timeout_add(1000, self.update_time)

    def update_time(self):
        self.remaining -= 1
        self.time_label.set_label(self.format_time(self.remaining))
        if self.remaining <= 0:
            self.on_stop_clicked(None)
            return False
        return True

    def on_pause_clicked(self, widget):
        if self.running:
            GLib.source_remove(self.timeout_id)
            self.pause_btn.set_label("恢复")
        else:
            self.start_timer()
            self.pause_btn.set_label("暂停")
        self.running = not self.running

    def on_stop_clicked(self, widget):
        if self.timeout_id:
            GLib.source_remove(self.timeout_id)
        # 从父容器中移除自己
        parent = self.get_parent()
        if parent:
            parent.remove(self)

三、学习资料方向

  • Gtk官方文档:重点看Gtk.ListBox和GLib.Timeout相关章节,了解列表项的动态管理和定时器回调机制;如果用Glade,重点学习Gtk复合控件的设计与加载方法。
  • Python-GObject绑定文档:学习如何用Python继承Gtk控件、处理信号、管理GLib的异步回调,这是Python操作Gtk的核心基础。
  • 自定义列表项教程:搜索“Gtk ListBox custom widget”相关内容,找分步实现的例子,学习如何将UI和逻辑封装到自定义控件中。
  • Gtk4入门教程:如果你用的是Gtk4,找一套完整的入门教程,熟悉窗口布局、控件生命周期、信号系统这些基础概念,对你理解整体实现至关重要。

内容的提问来源于stack exchange,提问作者francescoe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 04:55:36