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はインスタンス化するのに本質的にコストがかかることがわかりました。私は、それほど多くのGtkTextViewを作成しようとすべきではありませんでした。このスレッドのアドバイスに従って、代わりにGtkTreeViewを使用するようにコードを作り直します。

于 2012-04-26T07:25:50.553 に答える