Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.05.17;
Скачать: CL | DM;

Вниз

рисование компонент   Найти похожие ветки 

 
mnj   (2009-04-01 17:40) [0]

Доброго  дня.
Помогите, пожалуйста с такой штукой:
Нужно нарисовать матрицу из панелек
(цвет - индикация величины, пока не сделано)
по значениям из динамического массива
Это:
SetLength(Blocks,NumberOfRows,NumberOfBlocks);
               for I:= 1 to NumberOfRows do
               begin
                       for K:= 1 to NumberOfBlocks do
                       begin
                            Blocks[i-1,k-1]:= TPanel.Create(Self);
                            with Blocks[i-1,k-1] do
                            begin
                               Parent:= pnModel;
                               Left:= 20+(K-1)*15;
                               Top:= 20+(I-1)*20;
                               Width:= 15;
                               Height:= 20;
                               Color:= clBlue;
                               Tag:= I*10+K;
                            end; {of with}
                       end;
               end;

рисует медленно и с мерцанием. Можно ли сделать это быстрее и без мерцания?
И второй вопрос - как обрабатывать события компонентов, созданных во время выполнения, как в моем случае?


 
Игорь Шевченко ©   (2009-04-01 18:40) [1]


> Можно ли сделать это быстрее и без мерцания?


Можно.


> И второй вопрос - как обрабатывать события компонентов,
> созданных во время выполнения, как в моем случае?


Также, как обычно.

Рисовать можно например так:
Положить на форму PaintBox, на его событии OnPaint нарисовать нужное количество квадратиков.

В качестве тупого примера рисуется 1024 (32х32) квадратика

procedure TfMain.DrawMap(const Map: TMemoryMap; PaintBox: TPaintBox);
var
 Column    :  Integer;
 GridHeight:  Integer;
 GridWidth :  Integer;
 Row       :  Integer;
 I : Integer;
 BrushNew, BrushOld : HBRUSH;
begin
 GridHeight := PaintBox.Height div 32;
 GridWidth  := PaintBox.Width  div 32;
 for I := 0 to 1023 do begin
   Row    := I div 32;
   Column := I mod 32;
   BrushNew := CreateSolidBrush(TMemory.MapEntryColor(Map[I]));
   BrushOld := SelectObject(PaintBox.Canvas.Handle, BrushNew);
   Rectangle(PaintBox.Canvas.Handle, GridWidth*Column, GridHeight*Row,
     GridWidth*(Column+1), GridHeight*(Row+1));
   SelectObject(PaintBox.Canvas.Handle, BrushOld);
   DeleteObject(BrushNew);
 end;
end;

Получается сеточка из разноцветных квадратиков.


 
mnj   (2009-04-01 20:48) [2]

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


 
Игорь Шевченко ©   (2009-04-01 21:00) [3]

mnj   (01.04.09 20:48) [2]

Очень даже подходит для этого PaintBox, потому как он только средство отображения (ну и клик мыши тоже воспринимает). А объект с меняющимися свойствами - он отдельный и сам по себе, хотя бы и в массиве.

Если обратить внимание, то в процедуре рисования отображается состояние (цвет, кстати) именно объектов, другое дело, что объекты простые, но сложными быть им никто не мешает.

Мышкой щелкать тоже, кстати, просто

procedure TfMain.PaintBoxWholeMouseDown(Sender: TObject;
 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
 EntryIndex, EntryX, EntryY : Integer;
 GridHeight:  Integer;
 GridWidth :  Integer;
 PaintBox : TPaintBox;
begin
 PaintBox := Sender as TPaintBox;
 if Button = mbLeft then begin
   GridHeight := PaintBox.Height div 32;
   GridWidth  := PaintBox.Width  div 32;
   EntryX := (X div GridWidth);
   EntryY := (Y div GridHeight);
   EntryIndex := EntryY * 32 + EntryX;
   SelectWholeMapEntry(EntryIndex);
 end;
end;

Определили индекс объекта и делаем с ним, что хотим.

В моем случае (это карта вирутальной памяти процесса), в зависимости от состояния участка памяти в довольно крупном масштабе
(свободен, выделен, занят кодом, и т.п.), определяется его цвет, а при щелчке мышью конкретно этот участок отображается рядом более детально.
То есть, объекты налицо :)


 
mnj   (2009-04-01 21:33) [4]

Спасибо, попробую.


 
mnj   (2009-04-02 00:24) [5]

Это тоже все хорошо, я сделал вот так:

for I:= 1 to NumberOfRows do
               begin
                       for K:= 1 to NumberOfBlocks do
                       begin
                           with pbModel.Canvas do
                           begin
                               X:= 20+(K-1)*10;
                               Y:= 20+(I-1)*20;
                               dX:= 15;
                               dY:= 20;
                               Pen.Style:= psSolid;
                               Brush.Style:= bsSolid;
                               Pen.Color:= clBlack;
                               Brush.Color:= clGreen;
                               Rectangle(X,Y,X+dX,Y+dY);
                           end
                       end
               end;
Беда в том, что при перекрытии PaintBox каким-либо элементом, окном, например, картинка стирается. Как с этим бороться?


 
Игорь Шевченко ©   (2009-04-02 01:01) [6]


> Это тоже все хорошо, я сделал вот так:


Надеюсь, это код процедуры PaintBoxPaint


 
Amoeba ©   (2009-04-02 01:20) [7]


> Игорь Шевченко ©   (02.04.09 01:01) [6]
>
>
> > Это тоже все хорошо, я сделал вот так:
>
>
> Надеюсь, это код процедуры PaintBoxPaint

Судя по
> при перекрытии PaintBox каким-либо элементом, окном, например,
>  картинка стирается

похоже на  то, что надежда оказалась напрасной.


 
Amoeba ©   (2009-04-02 01:34) [8]

Как вариант, можно использовать DrawGrid и в нем раскрашивать ячейки. Я бы лично предпочел такой путь.


 
Германн ©   (2009-04-02 02:11) [9]


> Amoeba ©   (02.04.09 01:34) [8]
>
> Как вариант, можно использовать DrawGrid и в нем раскрашивать
> ячейки. Я бы лично предпочел такой путь.
>

+1
Я когда-то в некоей задаче пошёл именно таким путём.
Правда кол-во строк и колонок было изначально фиксированно. И нужны были Fixed Rows & Cols.


 
Игорь Шевченко ©   (2009-04-02 02:18) [10]

Amoeba ©   (02.04.09 01:34) [8]


> Как вариант, можно использовать DrawGrid и в нем раскрашивать
> ячейки. Я бы лично предпочел такой путь.


Можно. Но в моем случае (карта виртуальной памяти процесса) проще раскрасить PaintBox 32x32. И кода меньше :)


 
Германн ©   (2009-04-02 02:31) [11]


> Игорь Шевченко ©   (02.04.09 02:18) [10]

Я. конечно, уже многим надоел своими требованиями к вопросам, но ...
Без приведения в сабже "задачи", нет возможности дать "правильный ответ" на сабж, без включения телепатора.
А телепатор - вещь весьма мало предсказуемая.


 
Игорь Шевченко ©   (2009-04-02 02:43) [12]

Германн ©   (02.04.09 02:31) [11]

Это факт. Вот у автора вопроса есть уже выбор из двух вариантов.


 
ЮЮ ©   (2009-04-02 08:32) [13]


> mnj   (02.04.09 00:24) [5]
>
> Это тоже все хорошо, я сделал вот так:

> Беда в том, что при перекрытии PaintBox каким-либо элементом,
>  окном, например, картинка стирается. Как с этим бороться?
>


Важно не только как, но и где, т.е. каком обработчике стоит этот код.


 
mnj   (2009-04-02 12:44) [14]

Код стоит в обработчике открытия файла (стандартный диалог открытия файла, формат - текстовый). Задача - по условным цветовым кодам нарисовать модель геоэлектрического разреза, где каждый цвет обозначает определенную величину удельного электрического сопротивления. В геофизике при моделировании  этот разрез разбивается на заданное число блоков и имеет вид матрицы MxN, где M - число блоков по горизонтали (профилю), N - число блоков по вертикали (в глубину). Каждому блоку присваивается свое значение удельного электрического сопротивления, обозначаемое кодом (0..f), таким образом, зона из блоков с одинаковым значением представляет собой геологическое тело в разрезе. Необходимо менять значения сопротивления чтобы создавать тела с другим сечением. Формат входного файла изобретен автором программы инверсии данных (т.е. расчета геоэлектрического поля в разрезе в зависимости от пространственного положения источника поля) и от него я и вынужден отталкиваться. Вместо конкретных значений он использует коды: 0 - значение сопротивления 1, 1 - значение 2, 2 - значение 3 и т.д. до f (предел - 16 значений). в файле разрез выглядит вот так:
000000000000000000000000000000000
000000000111111100000000000000000
000000001111111110000000000000000
000000011111111111000000000000000
000000111111111111100000000000000
000001111111111111110000000000000
111111111111111111111111111111111
111111111111111111111111111111111
В PaintBox нарисовать это несложно, но изображение затирается (см. выше). приведенный в [5] код и относится к варианту с PaintBox. Матрица из панелек, создаваемая runtime - слишком медленно[1]. Попробуем DrawGrid;


 
mnj   (2009-04-02 13:25) [15]

Тогда еще возникает момент - как раскрасить отдельную ячейку DrawGrid?


 
Amoeba ©   (2009-04-02 15:22) [16]


> mnj   (02.04.09 13:25) [15]
>
> Тогда еще возникает момент - как раскрасить отдельную ячейку
> DrawGrid?

Кодом, написанным в OnDrawCell.


 
mnj   (2009-04-02 16:34) [17]

Все равно - рисование через канву затирается, поэтому очень неудобро восстанавливать изображение.
Такой вариант:
SetLength(Blocks,NumberOfRows,NumberOfBlocks);
               for I:= 1 to NumberOfRows do
               begin
                       for K:= 1 to NumberOfBlocks do
                       begin
                            Blocks[i-1,k-1]:= TPanel.Create(Self);
                            Blocks[i-1,k-1].Hide; //непоказывать блок
                            with Blocks[i-1,k-1] do
                            begin
                               Parent:= pnModel;
                               Left:= 20+(K-1)*15;
                               Top:= 20+(I-1)*20;
                               Width:= 15;
                               Height:= 20;
                               Color:= clBlue;
                               Tag:= I*10+K;
                            end; {of with}

                       end;
               end;
               OldBlocks:= NumberOfBlocks;
               OldRows:= NumberOfRows;
               for I:= 1 to NumberOfRows do
               begin
                       for K:= 1 to NumberOfBlocks do
                       begin
                               Blocks[i-1,k-1].Show;//теперь показывать
                       end;
               end;
ускорил процесс и убрал мерцание. Изображение также сохраняется.
Но можно ли еще ускорить вывод панелек?


 
Игорь Шевченко ©   (2009-04-03 01:28) [18]

mnj   (02.04.09 16:34) [17]

Было бы неплохо увидеть не только процедуру рисования, но и то место, откуда она вызывается. Иначе мы будем долго гадать, почему затирается и как ускорить


 
Германн ©   (2009-04-03 02:00) [19]


> Игорь Шевченко ©   (03.04.09 01:28) [18]

И так ясно что сия процедура вызывается "не оттуда, откуда нужно".
Ясен перец - нужно читать книги.
А вот ссылки на статьи по этой теме я не знаю.
Может Амёба знает?


 
mnj   (2009-04-03 02:16) [20]

Вот добил: прячу панель-контейнер, создаю в ней нужное количество панелек и показываю снова с готовым результатом.

               pnModel.Hide; //прячем панель
                if (OldBlocks > 0) and (OldRows > 0) then
                begin
                       for I:= 1 to OldRows do
                       begin
                       for K:= 1 to OldBlocks do
                               Blocks[i-1,k-1].Free; //стираем, если было что
                       end;
                end;
{-------------------------Рисование блоков-------------------------}

               SetLength(Blocks,NumberOfRows,NumberOfBlocks);
               for I:= 1 to NumberOfRows do
               begin
                       for K:= 1 to NumberOfBlocks do
                       begin
                            Blocks[i-1,k-1]:= TPanel.Create(Self);
                            with Blocks[i-1,k-1] do
                            begin
                               Parent:= pnModel;//родительская панель-контейнер - спрятана, поэтому "рисование" происходит быстро и скрыто.
                               Left:= 20+(K-1)*(pnModel.Width-20) div (NumberOfBlocks+1);
                               Top:= 20+(I-1)*pnModel.Height div (NumberOfRows*2);
                               Width:= (pnModel.Width-20) div (NumberOfBlocks+1);
                               Height:= pnModel.Height div (NumberOfRows*2);
                               Color:= ColorTable[ResistivityMatrix[i-1,k-1]];
                               Tag:= I*10+K;
                            end; {of with}

                       end;
               end;
               OldBlocks:= NumberOfBlocks;
               OldRows:= NumberOfRows;          
               pnModel.Show; //показываем все

3136 панелек рисовалось примерно 2 с (матрица 196х16), 1120 (80х14) штук - меньше секунды, 4536 штук (252х18) - примерно 5 с. Никакого затирания, естественно, и никакого мерцания.
Должен признаться, что хотел использовать шейп, но шейп не имеет фокуса ввода пользователя...


 
Игорь Шевченко ©   (2009-04-03 02:25) [21]


> 4536 штук (252х18) - примерно 5 с.


Ради интереса запустил свой проект (который с PaintBox :)
2048 клеточек рисуются мгновенно (ну то есть, совсем мгновенно).
Помещаю поверх окна своей программы окна других программ, убираю - окном моей программы рисуется, опять же, мгновенно.


 
MsGuns ©   (2009-04-03 09:05) [22]

>Должен признаться, что хотел использовать шейп, но шейп не имеет фокуса ввода пользователя...

А фокус и не нужен, достаточно просто ловить мышиный клик и определять какой контрол под ней находится


 
Jeer ©   (2009-04-03 15:38) [23]


> Игорь Шевченко ©   (03.04.09 02:25) [21]
>
>
> > 4536 штук (252х18) - примерно 5 с.
>
>
> Ради интереса запустил свой проект (который с PaintBox :
> )
> 2048 клеточек рисуются мгновенно (ну то есть, совсем мгновенно).
>


Отличный пример, Игорь.

Насчет прорисовки ( CPU 3 GHz ):
- 1024 рисуются за 9 ms
- 4096 * 38 ms
- 16 тыс за 135 ms


 
mnj   (2009-04-04 01:54) [24]

Спасибо за помощь


 
KilkennyCat ©   (2009-04-04 04:06) [25]


> Игорь Шевченко ©

Я бы все-таки сделал через буферный битмап, а потом bitblt - это гарантирует появление квадратиков всех сразу, если у кого-то вдруг 286 проц или видеодрайвер не установлен :)


 
mnj   (2009-04-04 15:26) [26]

>KilkennyCat ©   (04.04.09 04:06) [25]

>> Игорь Шевченко ©

>Я бы все-таки сделал через буферный битмап, а потом bitblt - это >гарантирует появление квадратиков всех сразу, если у кого-то вдруг 286 >проц или видеодрайвер не установлен :)

А где это - bitblt? Я не нашел такой.


 
Palladin ©   (2009-04-04 15:51) [27]


> А где это - bitblt? Я не нашел такой.

даже в гугле?


 
Игорь Шевченко ©   (2009-04-04 19:11) [28]

KilkennyCat ©   (04.04.09 04:06) [25]

Овчинка выделки не стоит



Страницы: 1 вся ветка

Текущий архив: 2009.05.17;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.01 c
2-1238647976
Evggeniy
2009-04-02 08:52
2009.05.17
с какой БД работать?


15-1237211479
@!!ex
2009-03-16 16:51
2009.05.17
Как забрать SVN репозиторий с сервера?


2-1238654080
Mozgan
2009-04-02 10:34
2009.05.17
Заголовок и URL Intrnet Explorer


15-1237091468
корнелий
2009-03-15 07:31
2009.05.17
Стенли Б. Липпман... Язык программирования C++. Вводный курс


15-1237292509
Unknown user
2009-03-17 15:21
2009.05.17
Просмотр связей между модулями в проектах Delphi