Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.05.17;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.004 c
2-1238660648
DmitriyR
2009-04-02 12:24
2009.05.17
Си и Delphi


15-1236677968
It's me
2009-03-10 12:39
2009.05.17
Восстановление БД по индексам?


2-1238705893
Maxwood
2009-04-03 00:58
2009.05.17
Разные картинки на Кнопке


15-1237283499
немо2
2009-03-17 12:51
2009.05.17
MS SQL сервер. Клиентские приложения подзависание.


15-1237156549
Германн
2009-03-16 01:35
2009.05.17
Это интересно





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский