这是一个说明问题的最小例子。单击该按钮时,应添加500个TextView对象,每个对象包含一些文本。实际发生的是,有一个短暂的延迟,500个空文本视图被添加,有更长的延迟,然后他们都一次填充文本和布局大小本身正确。代码如下:
import gtk.Button;
import gtk.Main;
import gtk.MainWindow;
import gtk.Notebook;
import gtk.ScrolledWindow;
import gtk.Statusbar;
import gtk.TextView;
import gtk.TextBuffer;
import gtk.UIManager;
import gtk.VBox;
import gtk.Window;
import std.stdio;
class UI : MainWindow
{
Notebook notebook;
this() {
super("Test");
setDefaultSize(200, 100);
VBox box = new VBox(false, 2);
notebook = new Notebook();
Button button = new Button("add lines");
button.addOnClicked(&addLines);
box.packStart(notebook, true, true, 0);
box.packStart(button, false, false, 2);
add(box);
showAll();
}
void addLines(Button b) {
VBox box = new VBox(false, 2);
for (int i = 0; i < 500; i++) {
auto tv = new TextView();
tv.getBuffer().setText("line");
box.packStart(tv, false, false, 1);
}
ScrolledWindow swin = new ScrolledWindow(box);
notebook.add(swin);
showAll();
}
}
void main(string[] args)
{
Main.init(args);
auto ui = new UI();
Main.run();
}
修改:this thread建议创建一堆文本视图本身就很昂贵,我应该使用树视图重写。
答案 0 :(得分:2)
GTK是事件驱动的,并使用消息泵。如果在回调中进行了长时间的操作,则永远不会给消息泵提供处理待处理消息的机会。您可以通过2秒的休眠替换回调中的代码,效果将是相同的:UI将在该时间片期间被冻结。
如果您无法拆分行动,请使用与gtk_events_pending文档中描述的相同的内容:
/* computation going on */
...
while (gtk_events_pending ())
gtk_main_iteration ();
...
/* computation continued */
在每次循环迭代之间调用,它会给GTK一些时间来处理通过添加小部件生成的事件。
答案 1 :(得分:1)
经过一些谷歌搜索和实验后,事实证明GtkTextViews实例化本质上是昂贵的,我不应该试图创建这么多。根据{{3}}中的建议,我将重新编写代码以使用GtkTreeView。