1

我目前正在编写一个类似于任务管理器的程序(类似于 Windows 的程序),并且我在 gtk+ 3 中使用树形视图作为 GUI。问题是,通过使树视图更新“实时”,滚动条停止正常运行。每次刷新树视图时,滚动条都会转到页面顶部。这是用于更新树视图的行:

        GObject.timeout_add_seconds(1, self.update_treeview)

这是函数 update_treeview:

def update_treeview(self):
    self.process_list_store.clear()
    p_list = create_list(self.properties, create_list_of_processes())
    for p in p_list:
        self.process_list_store.append(list(p))
    return True

如果重要的话,这就是我创建树视图的方式:

def create_treeview(process_list_store):
    treeview = gtk.TreeView(process_list_store)
    for i, col_title in enumerate(['Name', 'pid', 'Username', 'Memory usage', 'Cpu usage']):
        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn(col_title, renderer, text=i)
        column.set_sort_column_id(i)
        column.set_min_width(110)
        column.set_resizable(i)
        treeview.append_column(column)
    return treeview

树视图位于滚动窗口对象内:

    self.scrolled_window = gtk.ScrolledWindow(hexpand=True, vexpand=True)
    self.scrolled_window.set_policy(gtk.PolicyType.NEVER, gtk.PolicyType.AUTOMATIC)

我寻找可能更新树视图的其他方法,但我无法找到解决方案。我将不胜感激任何帮助来解决这个问题,谢谢!

编辑:这是完整的代码:

import psutil
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
from gi.repository import GObject


class MainWindow(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self, title="Task Manager")
        self.set_default_size(1000, 500)
        #basic objects in the program
        self.set_border_width(10)
        self.notebook = gtk.Notebook()
        self.grid1 = gtk.Grid(row_spacing=20)
        self.notebook.set_scrollable(True)
        self.add(self.notebook)

        #Processes Tab
        self.tab1 = gtk.Box()
        self.set_border_width(10)
        self.notebook.append_page(self.tab1, gtk.Label("Processes"))

        self.properties = ['name', 'pid', 'username', 'memory_percent', 'cpu_percent']
        p_list = create_list(self.properties, create_list_of_processes())
        print p_list

        #create a list store object for the tree view
        self.process_list_store = gtk.ListStore(str, int, str, str, str)
        for p in p_list:
            self.process_list_store.append(list(p))

        #create a window that can be scrolled
        self.scrolled_window = gtk.ScrolledWindow(hexpand=True, vexpand=True)
        self.scrolled_window.set_policy(gtk.PolicyType.NEVER, gtk.PolicyType.AUTOMATIC)
        self.grid1.attach(self.scrolled_window, 0, 0, 8, 10)

        #create a tree view and add it to the window
        self.tree_view = create_treeview(self.process_list_store)
        self.scrolled_window.add(self.tree_view)
        self.tab1.add(self.grid1)

        GObject.timeout_add_seconds(1, self.update_treeview)

    def update_treeview(self):
        self.process_list_store.clear()
        p_list = create_list(self.properties, create_list_of_processes())
        for p in p_list:
            self.process_list_store.append(list(p))
        return True


#create a list of dictionaries of processes and info about them
def create_list_of_processes():
    list_of_processes = []
    for proc in psutil.process_iter():
        try:
            pinfo = proc.as_dict(attrs=['pid', 'name', 'username', 'memory_percent', 'cpu_percent'])
        except psutil.NoSuchProcess:
            pass
        else:
            if not pinfo['username']:
                pinfo['username'] = 'SYSTEM'
            pinfo['cpu_percent'] = str(pinfo['cpu_percent'] / psutil.cpu_count()) + '%'
            pinfo['memory_percent'] = str(pinfo['memory_percent'])[0:6]
            pinfo['memory_percent'] = str(pinfo['memory_percent']) + '%'
            list_of_processes.append(pinfo)
    return list_of_processes


#create a tree view object
def create_treeview(process_list_store):
    treeview = gtk.TreeView(process_list_store)
    for i, col_title in enumerate(['Name', 'pid', 'Username', 'Memory usage', 'Cpu usage']):
        renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn(col_title, renderer, text=i)
        column.set_sort_column_id(i)
        column.set_min_width(110)
        column.set_resizable(i)
        treeview.append_column(column)
    return treeview


#create a list based on the desired properties
def create_list(properties, p_dict):
    p_list = []
    for dict in p_dict:
        small_p_list = []
        for prop in properties:
            small_p_list.append(dict[prop])
        p_list.append(small_p_list)
    return p_list


def main():
    window = MainWindow()
    window.connect("delete-event", gtk.main_quit)
    window.show_all()
    gtk.main()

if __name__ == '__main__':
    main()
4

1 回答 1

0

此更新对我有用:

def update_treeview(self):
    adjustment = self.scrolled_window.get_vadjustment()
    value = adjustment.get_value()
    self.process_list_store.clear()
    p_list = create_list(self.properties, create_list_of_processes())
    for p in p_list:
        self.process_list_store.append(list(p))
    GObject.idle_add(adjustment.set_value, value)
    return True

这是文档

不幸的是,这会导致窗口闪烁。最终的方法是逐行更新树视图。但这是很难编写的代码。

于 2018-04-07T11:18:37.880 回答