1

这是一个最小的例子来说明这个问题。单击按钮时,应添加 500 个 TextView 对象,每个对象都包含一些文本。实际发生的情况是有一个短暂的延迟,添加了 500 个空的 TextView,有更长的延迟,然后它们都立即填充了文本,并且布局本身的大小也正确。下面的代码:

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();
}

编辑这个线程表明创建一堆文本视图本质上是昂贵的,我应该使用树视图重写。

4

2 回答 2

2

GTK 是事件驱动的,并使用消息泵。如果在回调中您执行了一个冗长的操作,那么您永远不会给消息泵处理待处理消息的机会。您可以将回调中的代码替换为 2 秒的睡眠,效果是一样的:在该时间片内 UI 将被冻结。

如果您无法拆分您的操作,请使用gtk_events_pending文档中描述的 d 等效项:

/* computation going on */
...
  while (gtk_events_pending ())
      gtk_main_iteration ();
...
/* computation continued */

在每个循环迭代之间调用,它会给 GTK 一些时间来处理通过添加小部件生成的事件。

于 2012-04-25T10:54:59.947 回答
1

经过更多的谷歌搜索和试验,事实证明 GtkTextViews 实例化本质上是昂贵的,我不应该尝试创建这么多的。根据此线程中的建议,我将修改我的代码以改用 GtkTreeView。

于 2012-04-26T07:25:50.553 回答