PyGTK的GtkComboBox.clear_all()非常慢

时间:2015-07-17 13:20:07

标签: python pygtk

在我的python脚本中(使用Glade进行界面构建)我有一些组合框,当选项发生变化时会定期重新填充。

当选项列表很短时,这样可以正常工作,例如10个左右。然而它也可以变得更长,大约100个选项也不例外。现在的问题是清除列表非常慢,程序在该特定行上挂起大约需要10秒钟。

这是代码的一个片段,其中使用remove_all()清除组合框,然后使用append_text()再次填充。我做了一些简单的测试,发现它确实是第二行,remove_all()调用,这是罪魁祸首。其余的代码运行得很快。

    # Clear the combobox
    self.add_tour_selector.remove_all()

    # Populate the combobox.
    ids = [t['id'] for t in self.tours]
    for i in sorted(ids):
        self.add_tour_selector.append_text(i)

    self.add_tour_selector.set_active(0)

我正在寻找大幅加快速度的方法。必须等待我的脚本再次开始响应这一长期并不好玩。这些组合框实际上也必须一直重新填充,因此很难尝试跟踪更改选项并更新它们。

add_tour_selector取自Glade文件,如下所示:

        self.add_tour_selector = self.builder.get_object('add_tour_selector')

print这会给<ComboBoxText object at 0x7f3bdcb1b870 (GtkComboBoxText at 0x2ba22a0)>

ComboBoxText的填充方式如下:

    # Populate the combobox.
    ids = [t['id'] for t in self.tours]
    for i in sorted(ids):
        self.add_tour_selector.append_text(i)

    self.add_tour_selector.set_active(0)

一个特别慢的(有很多条目 - 至少100个 - 也是ComboBoxText个对象)填充如下:

    # clear the combobox
    self.bookings_tour_selector.remove_all()

    # Populate the tour selector.
    self.bookings_tour_selector.append('0', 'all')

    for s in self.schedule:
        d = s['datetime'].strftime('%d/%m')
        self.bookings_tour_selector.append(str(s['number']), '%s %s'% (d, s['tourid']))

remove_all()函数非常慢,其余代码很快。

1 个答案:

答案 0 :(得分:0)

GtkComboBox.remove_all只调用(内部)ListStore.clear(),因此用ComboBox + Model替换ComboBoxText几乎没什么好处。

然而,清除列表中100个元素的10秒钟听起来非常慢。调试(和计时)这些事情并不容易。小部件在使用时基本上可以转换为两个部分:&#39;命令&#39;部分和&#39;图形&#39;部分,其中图形部分是异步执行的 - 它被转换为在程序的主循环空闲时执行的代码。因此,remove_all可能会触发程序中较早的一系列图形命令,这可能会很慢。

另外,很大程度上取决于你是否已经定义了要排序的列表 - 排序往往很慢。

最后,速度还取决于您是否定义了一个复杂的渲染过程。

这是一个简单的例子,其中remove_all是瞬时的(据我所知)。我已将元素数量设置为1000 - 它实际上是&#39;填充&#39;这显然很慢,可能是因为它更新了每个循环中的图形:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  test_remove_all.py
#  
#  Copyright 2015 John Coppens <john@jcoppens.com>
#  
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  
#  


from gi.repository import Gtk

class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connect("destroy", lambda x: Gtk.main_quit())
        self.set_size_request(200, -1)

        self.clear_btn = Gtk.Button("Clear")
        self.clear_btn.connect("clicked", self.clear_btn_clicked)
        self.add_btn = Gtk.Button("Add 100")
        self.add_btn.connect("clicked", self.add_btn_clicked)
        self.label = Gtk.Label("0 elements")
        self.combo = Gtk.ComboBoxText()
        self.add_btn_clicked(self)

        self.vbox = Gtk.VBox()
        self.vbox.pack_start(self.clear_btn, False, True, 0)
        self.vbox.pack_start(self.add_btn, False, True, 0)
        self.vbox.pack_start(self.label, False, True, 0)
        self.vbox.pack_start(self.combo, False, True, 0)

        self.add(self.vbox)
        self.show_all()

    def clear_btn_clicked(self, btn):
        self.combo.remove_all()

    def add_btn_clicked(self, btn):
        for n in range(100):
            self.combo.append_text("String %d" % n)

        self.combo.set_active(1)
        model = self.combo.get_model()
        self.label.set_text("%d elements" % model.iter_n_children(None))

    def run(self):
        Gtk.main()


def main(args):
    mainwdw = MainWindow()
    mainwdw.run()

    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

多次单击添加100,然后单击清除 - 它非常快。事实上,我试过几千年。只有在1000年代,事情变得缓慢。