Проблема производительности gtkd при добавлении большого количества текстовых просмотров одновременно
Вот минимальный пример, чтобы проиллюстрировать проблему. При нажатии кнопки должно быть добавлено 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();
}
Редактировать: этот поток предполагает, что создание набора текстовых представлений является по сути дорогостоящим, и что я должен переписывать с использованием дерева.
2 ответа
После еще нескольких поисков в Google и экспериментов выясняется, что GtkTextViews по своей сути дорогостоящи для создания экземпляров, и я не должен был пытаться создать их так много. Согласно совету в этой теме, я буду переделывать свой код, чтобы использовать вместо него GtkTreeView.
GTK управляется событиями и использует насос сообщений. Если при обратном вызове вы выполняете длительную операцию, вы никогда не дадите насосу сообщений обработать ожидающие сообщения. Вы можете заменить код в вашем обратном вызове на 2 секунды, эффект будет таким же: пользовательский интерфейс будет заморожен в течение этого отрезка времени.
Если вы не можете разделить свои действия, используйте d-эквивалент того, что описано в документации gtk_events_pending:
/* computation going on */
...
while (gtk_events_pending ())
gtk_main_iteration ();
...
/* computation continued */
Вызывается между каждой из ваших итераций цикла, это даст GTK некоторое время для обработки событий, которые вы сгенерировали, добавив свои виджеты.