在我的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()
函数非常慢,其余代码很快。
答案 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年代,事情变得缓慢。