Forum > Russian
Три вопроса новичка: OnPaint, ImageList и логика программы
majolika:
Привет!
Имеется три новичковых вопроса о рисовании на контроле. Ради самообразования я пишу «сапёра».
Вопрос 1: OnPaint
Когда я нажимаю кнопку «старт», то показываю минное поле и заполняю его квадратами. Затем, когда я кликаю на минном поле и рисую мину. Но минное поле полностью перерисовывается, все квадраты — как ветром сдувает, и поверх рисуется мина, которая тоже исчезает при следующем клике.
Почему?
Вопрос 2: ImageList
ImageList — удобный контрол, но я обнаружил одну странную вещь: когда ярисую одну и ту же картинку при помощи ImageList и при помощи Canvas.Draw, это даёт разные результаты.
Почему?
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---ImageList1.Resolution[24].Draw(Bevel1.Canvas, x, y, 0, True);
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Field.Canvas.Draw(x, y, Picture_Loaded_From_TImage_Placed_On_The_Form);
На приаттаченной картинке показана разница минного поля:
фрагмент слева, более яркое минное поле — ImageList
фрагмент справа, более тёмное минное поле — Canvas.Draw
(просто на форму кидаю невидимый Timage, в Form.OnCreate подгружаю как TBitmap и рисую)
Пятой точкой чую, что собака зарыта в том, что TImage и TImageList как-то по-разному работают с загруженными изображениями, но, блин, где логика?!
«Изображение» и «список изображений» — исходя из названия, одно и то же, только в первом случае — в единственном экземпляре, во втором — в ассортименте, так сказать.
Вопрос 3: логика программы
Первый клик на кнопке «старт» работает отлично, а последующие — никак не работают.
Почему?
Ниже минимальный proof-of-concept код:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit test_unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls; type { TForm1 } TForm1 = class(TForm) Bevel1: TBevel; Button1: TButton; ImageList1: TImageList; procedure Bevel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Bevel1Paint(Sender: TObject); procedure Button1Click(Sender: TObject); private public end; var Form1: TForm1; BoxSize: Integer = 24; FieldRow: integer = 10; FieldCol: integer = 10; Button1Clicked: Boolean = False; DrawABomb: Boolean = False; CoordX, CoordY: Integer; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject);begin Button1Clicked := True; Bevel1.Width := FieldCol * BoxSize; Bevel1.Height := FieldRow * BoxSize; Bevel1.Show;end; procedure TForm1.Bevel1Paint(Sender: TObject);var x, y: Integer;begin if Button1Clicked then begin for x := 0 to FieldCol - 1 do begin for y := 0 to FieldRow - 1 do begin ImageList1.Resolution[24].Draw(Bevel1.Canvas, (x * BoxSize), (y * BoxSize), 0, True); end; end; Button1Clicked := False; end; if DrawABomb then begin ImageList1.Resolution[24].Draw(Bevel1.Canvas, CoordX, CoordY, 1, True); DrawABomb := False; end;end; procedure TForm1.Bevel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);begin if Button = mbLeft then begin DrawABomb := True; CoordX := X; CoordY := Y; Bevel1.Repaint; end;end; end.
Seenkao:
--- Quote ---Но минное поле полностью перерисовывается, все квадраты — как ветром сдувает, и поверх рисуется мина, которая тоже исчезает при следующем клике.
--- End quote ---
При каждом клике, поле должно перерисовываться, это по сути правильно. Не хотите чтоб перерисовывалось поле, значит надо отрисовывать определённый квадрат (квадраты) который открыли. А это другая логика, отличная от той, что используете вы.
На вашу логику надо накладывать всё, что уже открыто.
majolika:
Спасибо, Seenkao!
Но мне уже помогли со всеми возникавшими вопросами в англоязычной части форума. Там всё несколько оживлённее, нежели тут, в русскоязычной разделе.
Я рисовал прямо на контроле, что в данном случае не очень-то правильно.
В общем, я уже почти со всем разобрался и почти завершил свою первую программу на Lazarus: вариацию Сапёра с элементами RPG. Сейчас навожу последние штрихи.
majolika:
Но с одной штукой я пока не разобрался. Может, у вас найдётся время помочь?
Я там рисую маленькую рукотворную анимацию при помощи таймера.
Конструкция базово такая:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure StartAnimation; AnimationFrame := 0; Timer1.Enabled := True; procedure TForm1.Timer1Timer; // рисуем кадр анимации if AnimationFrame > AnimationFramesCount then StopAnimation; procedure StopAnimation; Timer1.Enabled := False;
И при определённых условиях в обработчике событий мыши вызывается StartAnimation.
Проблема в том, что после вызова StartAnimation цикл обработки событий спокойно продолжается. А мне надо как-то его притормозить, поставить на паузу, пока анимация не отрисуется, т.е. чтобы программа ждала конца анимации и уже потом продолжала работать.
Щас, пока писал, пришла в голову мысль, что, может, просто вставить пустой цикл, выполняющийся до тех пор, пока Timer.Enabled не станет False?
Но это какое-то топорное решение (если оно, вообще, будет работать). Может, есть какое-то более правильное решение?
Seenkao:
Надо создать флаг, который будет включаться, когда проигрывается анимация. Если флаг включен, то значит события ни какие не обрабатываем и выходим из обработки. Если выключен, то обработка событий происходит.
Navigation
[0] Message Index
[#] Next page