Помощь новичкам

Хотя лично меня приятно удивило, что в отличие от шарпа, в Pascal Abc . Net автоматически инициализирует как статические, так и ссылочные типы.

Сергей, не исключено, что я использую устаревшие примеры работы с графикой, но:

  1. даже блокировка автоматической отрисовки через вывод на bitmap вместо экрана, чтобы за раз вывести всё сразу, всё равно не справляется, если вывод не синхронизирован с частотой обновления монитора (v-sync). В крайнем случае, на трёх “квадратных” и пяти “широких” мониторах с частотой не кратной 60Гц.

  2. я не нашёл пример правильной работы для вывода в GraphWPF, например, нескольких подвижных линий или кругов:

uses graphwpf;

begin
  Window.Height := 600;
  Window.Width := 800;
  Window.CenterOnScreen;
  
  var(a, b) := (0, 5); //линия 1 + смещение 1
  var(c, d) := (0, 5); //линия 2 + смещение 2
  
  repeat
    Line(a, 0, 800 - a, 600);
    Line(a, 600, 800 - a, 0);
    
    Line(0, c, 800, 600 - c);
    Line(0, 600 - c, 800, c);
    
    Ellipse(400, 300, 10 + b,10 + d);
    DrawCircle(400,300,15+b+d);
    if (a + b < 0) or (a + b > 800) then b := -b;
    if (c + d < 0) or (c + d > 600) then d := -d;
    a += b; c += d;
    Sleep(10); // подбирая задержку можно уменьшить мерцание и разрывы
    Window.Clear; //cls
  until 1 = 0;
// зациклил, так как не нашёл простой аналог KeyPressed без событий и лишних модулей
end.

Изображение постоянно мерцает и процесс рандомно грузит от 3%-5%-10% ЦП как на i3, так и i5.

  • Как можно переделать на новый лад, чтобы без дёрганий и мерцания?

Также недавно заметил, что некоторые (не все) WindowsForm и WPF приложения мигают при изменении размера формы, иногда лишь некоторые элементы.

В GraphWPF смотрите BeginFrameBasedAnimation. Ну и, соответственно, примеры: Помощь\Примеры\Graphics\GraphWPF\ и там anim1.pas, anim2.pas, anim4.pas. Собственно, пример в последнем файле.

Что вы под этим понимаете? Под автоматической инициализацией можно много что понимать. И большинство вариантов - в паскале и C# работает одинаково.

v-sync это только замедление рисования (ради экономии ресурсов). Он так же может сделать картинку более стабильно лагающей. Но он не может ускорить рисование.

А рисование на битмап не может быть “даже”. Таким образом реализовано LockDrawing в GraphABC. И, неожиданно (нет), там это больше 20fps не даёт принципиально.

Как исправить уже написали, но при чём тут вообще центральный процессор? Графика то вся на графическом.

Кошмар. Это удаляет все нарисованные объекты (так устроен WPF), а потом рисует их снова. Конечно будет мерцать

Сергей, попробуйте на Паскале и на шарпе пример:

begin
  var s: string;
  var D: DateTime;
  var p: object;
  
  Print('[', s, ']', s.gettype, '='); if s <> nil then Print('не'); Println('пусто');
  Println('[', D, ']', D.gettype);
end.

По моему наблюдению, Vsync не только экономит ресурсы за счёт ожидания начала синхронизированной рисовки, но и избавляет от нежелательных разрывов, например, при частоте кадров 60/с на физической частоте 75Гц. ( Хотя наш админ мог заблокировать или изменить некоторые важные настройки,)

Меня тоже удивило, что даже на внешней графической карте ЦП процесса скачет от 3%-5% до 7%-10%, с другой стороны - локальные политики и Касперский.

Спасибо, Вадим. Разберу подробнее.

А как правильно ждать буфер? Или тоже через рисовку на bittmap? И не понял как сделать ожидание любой клавиши как KeyPressed.

string особенные, это единственное что в C# инициализирует с nil в то время как паскаль с ''. И вообще то - можно прописать сразу var s := '' или var s: string := nil. А та инициализация что сейчас - навязчивая и существует ибо наследие аля атрофизм.

Записи не бывают nil, там нечего инициализировать. Правда в C# нету значений поумолчанию у полей. Но в вашем примере они нигде не задействуются.

Ну а object, конечно, nil. И в C# тоже.

Конечно, в C# так же есть ошибка аля “использование не инициализированной переменной”. Вот только это защита от дурака, вроде её можно отключить с помощью #pragma. Ну и в целом - использовать не инициализированные переменные таки плохо.

Если на мониторе поддерживающем 75фпс программа всё равно выбирает 60фпс (и нет настройки) - это проблема программиста. А точнее его говнокода.

В GraphWPF - никак. Ждать vsync это в OpenGL и т.п. низкоуровневых библиотеках. Если надо выполнять анимацию - используйте процедуру покадровой анимации, которую вам уже дали выше.

procedure BeginFrameBasedAnimation(Draw: procedure; frate: integer := 61);
  1. как узнать текущую частоту монитора?
  2. как можно переписать код из примера
BeginFrameBasedAnimation(()->
    foreach var ball in a do
      ball.Step
  );

с указанием правильной частоты?

  1. почитал немного корявостей на сайте Микрософт и касательно оптимизации WPF:

и

Получается, даже повышение частоты далеко не всегда даёт относительно стабильное количество кадров?

Спасибо.

На ЖК мониторах стандартная частота - 60 кадров в секунду. Установка значения 61 по умолчанию позволяет немного опередить стандартную и перерисовка - без скачков. Можно ускорить, указав вторым параметром скажем 120.

Я сам последний раз делал это, вроде, через какое то WinAPI. Сейчас уже не помню, самому придётся искать скоро… Но лучше вообще иметь настройку.

Внимательно посмотрите на описание BeginFrameBasedAnimation которое вы сами же скинули. Ибо ответ уже в нём.

А теперь без корявости автоматического перевода:

You may discover that your custom drawing runs at different speeds on different computers. This is because your custom drawing is not frame-rate independent.

Вот это про НЕ_покадровую анимацию. То есть ту, которая не ждёт отрисовки, а добавляет объекты на экран - когда придётся.

The CompositionTarget.Rendering event causes WPF to continuously animate. If you use this event, detach it at every opportunity.

Это значит что надо не забывать убирать обработчик этого эвента, когда покадровая анимация перестала быть нужна, чтоб лишний раз не тратить производительность.

@Admin а вот тут не хорошо вышло. Процедура RenderFrame, присваиваемая этому эвенту - не открепляется никогда! А надо откреплять в EndFrameBasedAnimation. И прикреплять в BeginFrameBasedAnimation.

Ещё одна подпроблема: как самому конвертировать большие файлы в формате Linux на/с Windows ? CR LF <> LF

Разобрался, что можно просто читать по строкам через ReadLn, а писать через Write и добавлять (#10)

Если дело в кодировке только переносов строк - это легко.

  1. Текстовые файлы редко бывают такие уж большие, поэтому WriteAllText(ReadAllText().Replace(#13#10, #10)) обычно сработает.
  2. Если у вас действительно есть текста на несколько гигабайт (откуда???) - читайте по строкам (ReadLines) и записывайте через System.IO.File.

А стандартные паскалевские типы вроде TextFile - лучше не использовать, они реализованы как костыльные башни стоящие на System.IO.File.

Немного жаль, что кроме потоков нет простого способа (или плагина) сразу присвоить переменной внешние текстовые или другие данные. Я предварительно обработал массив, добавляя паскалевские кавычки и разделяя элементы запятыми, но это действует лишь для коротких строк, что, видимо, ограничено IDE.

Поэтому даже подготовленные элементы, например, через

  var f:=OpenWrite('spisok.txt');
  for var v:=50 to 65535 do Write(f,'''',ChrUnicode(v),''',');
  Write(f,'''.''');
  f.Close;

не получается присвоить как

var ls:array of string:=({$include 'spisok.txt'});
// ОШИБКА: Встречено '','', а ожидалось ';'

Или что-то другое не так?

Ростислав, не очень понятно, что Вы вообще хотите сделать. Пока Вы написали, что немного жаль, что нельзя нормально поджарить котлету в кастрюле :slight_smile: Зачем? Надо в кастрюле? или надо котлету? или поджарить?

Глядя на Ваш код приходит в голову что-то вроде

   var a := ReadAllLines('a.txt');

или

   var b := ReadAllText('b.txt');

а потом разбирать строку/строки. Или это не совсем то, что Вы хотите? Напишите, для чего это нужно.

Постарайтесь не начинать плакаться, а разбираться самому когда что то не так. Сильно отбивает желание помогать. Можно было хотя бы на ошибку посмотреть, в ней явно говорится не про запрет, а про то что вы с синтаксисом накосячили.

И чем вам потоки не понравились? Создаёте StreamReader и .ReadToEnd, проще некуда. Если это происходит 1 раз при загрузке программы - вы не заметите влияния на производительность.


Кроме всего прочего, char и word занимают одинаковый объём, и преобразование 1 к другому - только визуальное (когда оно через char() и word() а не функцию вроде ChrUnicode). А заполнение инициализатором и через for - будет одинаково работать, всё равно это:

var a: array of T := (A,B,C);

Разворачивается в:

var a := new T[3];
a[0] := A;
a[1] := B;
a[2] := C;

Сергей, спасибо за уточнение, буду иметь в виду. Это не плаканье, а непонимание: пару часов потратил, но так и не нашёл почему при всей простоте и фактически неограниченных строках нельзя вставить ($include) из файла внешний массив постоянных данных так, чтобы после компиляции обойтись без лишнего файла. Если с потоками и ресурсами относительно ясно, то с “сырыми” файлами наверно есть тонкости.

К сожалению, консольная версия выдаёт такую же ошибку, так что проблема немного ширее или же не то.

Ладно, насколько правильно я понял, что директива для вложение внешних файлов предназначена исключительно для небольших вставок и кода?

Не представляю на что вы там 2 часа могли потратить. По моему вы преувеличиваете уровень своих стараний в поиске проблемы. Поэтому и говорю что вы пришли поплакаться. И тон вашего оригинального обращения это только подтверждает.

Я добавил знак переноса строки (чтоб IDE не сдохла на следующем шагу):

begin
  var f:=OpenWrite('spisok.txt');
  for var v:=50 to 65535 do Write(f,'''',ChrUnicode(v),''','#10); // добавил #10
  Write(f,'''.''');
  f.Close;
end.

И в отдельном файле вместо $include вставил полученный текст. И вуаля, сразу видно что вы сделали не так:


Но как я и сказал, это изначально была плохая идея. В данном случае использование кодогенераторов - не оправданно.

Есть ли какой-нибудь способ сделать такое, раз уж компилятор отказывается принимать присваивание после params?

%D0%91%D0%B5%D0%B7%D1%8B%D0%BC%D1%8F%D0%BD%D0%BD%D1%8B%D0%B94

Мелкие вопросы нужно задавать в отведенных для этого темах (например, вопросы новичков), а не заводя всякий раз новую тему.

Нет, никак

1 лайк
  1. Это не нужно, в params можно передать 0 элементов и получите массив из 0 элементов в подпрограмме, ничего там не надо присваивать.

  2. Если так уж надо было бы - через отдельную перегрузку.

  3. Вложенные external подпрограммы сломаны в данный момент:
    https://github.com/pascalabcnet/pascalabcnet/issues/2075

И это опять Колян.

PascalABCCompiler.Core v3.5.0.2217 (27.07.2019), debug version
Runtime version: 4.0.30319.42000
OS version: Microsoft Windows NT 6.1.7601 Service Pack 1
Processor count: 2
WorkingSet: 93436 kb

Имеется вот такой вот прекрасно работающий код - https://www.yadi.sk/d/NHPIhXkgWhWGFA

Компилирую всегда через Ctrl+F9.

При его компиляции происходит вот это:

%D0%91%D0%B5%D0%B7%D1%8B%D0%BC%D1%8F%D0%BD%D0%BD%D1%8B%D0%B9

Строк на самом деле всего ВОСЕМЬСОТ30, а пишет что их ДЕВЯТЬСОТ30 - что это за свистопляска?