UI progressbar не обновляется на экране
Значит так. Не сильно уверен, что это правильная тема, но всё-таки спрошу.
Пишу скрипт для After Effects на ExtendedScript (диалект ECMAScript Javascript и ActionScript ). Сильно похож на Javascript, однако. Проблема в следующем. У меня есть основная задача скрипта, которая выполняется в основном цикле. Количество шагов цикла мне известно. Допустим их 10. Я хочу чтобы текстовая метка UI вела себя так: 1/10,2/10,...,10/10 Внутри цикла обновляю метку счетчиком цикла. Так вот итоговое UI скачет или сразу 1/10->10/10, или успевает показать 2/10. В любом случае не выводит информацию обо всех шагах цикла. Такое ощущение, как "подвисает". Подозреваю что основной цикл ей просто "не даёт слова". Если вставлять в основной цикл "alert", то UI обновляется. Как это победить? Код ниже //Это счетчик - простая текстовая метка var counter = new Window("palette"); counter.prompt = counter.add("statictext",[0,0,180,20]); counter.prompt.text = "Script is running"; Ниже цикл (убрал всё ненужное) for (i = 1; i <= NumOfStrings; i++) { в counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames"); counter.update(); // Здесь основной цикл } |
Цитата:
У вас цикл в цикле? |
Цитата:
for (i = 1; i <= NumOfStrings; i ++) { // Основной цикл counter.prompt.text = ("Обработано " + i+" / " + NumOfFrames + " кадров"); //Присвоение тексту счетчика нового значения counter.update(); // Рефреш UI? который по идее должен работать for (j = 0; j < ProjectCount; j++) { // Внутренний цикл } } |
ice99,
NumOfStrings или NumOfFrames? Вложенный цикл должен выполниться NumOfStrings раз? Во вложенном цикле, случайно, не меняются i или NumOfStrings? |
Цитата:
ТОЛЬКО ЧТО. У меня скрипт отработал нормально, прошёл от 1 до 10. Думал "победа". Но нет. Тут же запускаю и 1,2,пауза,10. Еще раз повторюсь, если перед counter.update(); ставить alert ("Hi!") // или alert (i); counter.update(); То counter отрабатывает отлично 1,2,3,4,5,6,7,8,9,10. Ставил $.sleep(100); не помогает Может дело в синхронном\асинхронном выполнении? |
Цитата:
Не знаю этого пакета - может, там есть средства заставить работать в синхронном режиме? |
Мало знаком с этим диалектом, но свое мнение выскажу.
Цикл for работает очень быстро, а метод .update() медленно, поскольку пропускается через большую библиотеку. Поэтому цикл for успевает сделать все 10 обновлений prompt.text, пока выполнится 2 или 3 итерация update(). Все последующие итерации update() тоже срабатывают, но этого не видно, поскольку все они показывают последнее 10-е обновление prompt.text. Оптимальное решение, если update() принимает callback-функцию (нужно смотреть документацию). Тогда .prompt.text каждый раз будет обновляться только после выполнения очередного .update() for (i = 1; i <= NumOfStrings; i++) { var fn = function(i) { counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames"); } counter.update(fn); // Здесь основной цикл } Если callback-функции не предусмотрено, то можно использовать setTimeOut или что его заменяет в данном диалекте: for (i = 1; i <= NumOfStrings; i++) { var fn = function(i) { counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames"); } setTimeOut(fn, 12); counter.update(); // Здесь основной цикл } Но это конечно хуже. Задержку можно подобрать методом проб. или замерить в консоли время выполнения .update() Все. Где-то так :) |
senex,
Все эти танцы с бубном в данном случае не помогут: в цикле быстренько позапустятся все функции или таймауты, и исполнятся они практически одновременно. Таймаут не задерживает выполнение цикла, а задерживает выполнение функции, указанной в нем. Помочь может только рекурсивное выполнение таймаута. var i = 0; function fn() { i++; counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames"); counter.update(); // вложенный цикл if(i < NumOfStrings) setTimeout(fn, 1000); } fn(); setTimeout в ExtendScript нет, но можно написать через sleep $.setTimeout = function(func, time) { $.sleep(time); func(); }; |
Часовой пояс GMT +3, время: 06:23. |