"EhLib.Com" https://forum.ehlib.com/ru/ |
|
Отрисовка границ ячеек https://forum.ehlib.com/ru/viewtopic.php?f=4&t=148 |
Страница 1 из 1 |
Автор: | Andrew Deviatikh [ 15 апр 2012, 18:52 ] |
Заголовок сообщения: | Отрисовка границ ячеек |
Существует ли в Ehlib какой-нибудь штатный способ изменить отрисовку границ у ячеек TDBGridEh? Или только путём рисования на канвасе? Пример конкретной задачи - нужно изменить толщину и цвет правой границы только определённых ячеек (в зависимости от их содержимого, например). Сейчас данную задачу решаем следующим образом - в OnDrawColumnCell засовывается следующий код: Код: if *некое условие* then begin (Sender as TCustomDBGridEh).Canvas.Pen.Color := clBlack; (Sender as TCustomDBGridEh).Canvas.Pen.Width := 2; (Sender as TCustomDBGridEh).Canvas.MoveTo(Rect.Right, Rect.Top); (Sender as TCustomDBGridEh).Canvas.LineTo(Rect.Right, Rect.Bottom); end; Данный метод работает, но вызывает ряд проблем с отрисовкой грида. Так, например, если включен OptionsEh.dghExtendVertLines, то "продолжения" вертикальных границ ячеек начинают всегда прорисовываться толщиной в 2 пикселя, а при быстрой горизонтальной прокрутке грида появляются артефакты прорисовки. Что можете порекомендовать? |
Автор: | Administrator [ 22 апр 2012, 22:27 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Добрый день. В текущей версии библиотеки можно влиять только на два базовых цвета линий. DBGridEh1.GridLineColors.DarkColor - цвет линий разделяющей фиксированные ячейки. DBGridEh1.GridLineColors.BrightColor - цвет линий разделяющей ячейки c данными. После прорисовки не забывайте возвращать старое значения свойств объектов канваса Код: OldColor := (Sender as TCustomDBGridEh).Canvas.Pen.Color; OldWidth := (Sender as TCustomDBGridEh).Canvas.Pen.Width; (Sender as TCustomDBGridEh).Canvas.Pen.Color := clBlack; (Sender as TCustomDBGridEh).Canvas.Pen.Width := 2; (Sender as TCustomDBGridEh).Canvas.MoveTo(Rect.Right, Rect.Top); (Sender as TCustomDBGridEh).Canvas.LineTo(Rect.Right, Rect.Bottom); (Sender as TCustomDBGridEh).Canvas.Pen.Color := OldColor; (Sender as TCustomDBGridEh).Canvas.Pen.Width := OldWidth; Best regards Admin |
Автор: | GoldMedium [ 03 мар 2021, 13:36 ] | |||
Заголовок сообщения: | Re: Отрисовка границ ячеек | |||
Прошло почти 9 лет, очень надеюсь, что в версии 10.x функционал в плане отрисовки линий расширился. Благодаря примеру выше я могу отрисовать вертикальные линий для заданных строк (чёрные линии на Screen1.png). Подскажите, пожалуйста, а как задать цвет отрисовки горизонтальных линий (сверху и снизу) для заданных строк (красные линии на Screen1.png)? И ещё как задать вертикальные и горизонтальные линии для текущей выделенной строки (красные линии на Screen2.png)? Очень надеюсь на Вашу помощь! Спасибо P.S. В документации всё перерыл - не нашёл решения
|
Автор: | EhLibSupport [ 04 мар 2021, 00:29 ] | |||
Заголовок сообщения: | Re: Отрисовка границ ячеек | |||
Добрый день. Для отрисовки окантовки ячеек грида вы можете использовать событие TColumnEh.OnAdvDrawDataCell Обработчик события необходимо присвоить каждой колонке грида. В событии понадобиться обращения к protected методам грида. Код: type TDBGridEhCrack = class(TCustomDBGridEh); а также возможность обращения к следующей записи грида для корректной отрисовки нижней линии для окантовки следующей ячейки. Код: if (AreaCell.Y < Grid.InstantReadRecordCount - 1) then begin try Grid.InstantReadRecordEnter(AreaCell.Y + 1); NextRowIsSpecial := MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1; finally Grid.InstantReadRecordLeave; end; end; Полный код обработчика события приведен ниже: Код: type TDBGridEhCrack = class(TCustomDBGridEh); procedure TForm1.DBGridEh1Columns0AdvDrawDataCell(Sender: TCustomDBGridEh; Cell, AreaCell: TGridCoord; Column: TColumnEh; const ARect: TRect; var Params: TColCellParamsEh; var Processed: Boolean); var Grid: TDBGridEhCrack; NextRowIsSpecial: Boolean; begin Grid := TDBGridEhCrack(Sender); NextRowIsSpecial := False; if (MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1) then begin Params.Background := $006DD3EB; Params.Font.Style := [fsBold]; end; Grid.DefaultDrawColumnDataCell(Cell, AreaCell, Column, ARect, Params); if (AreaCell.Y < Grid.InstantReadRecordCount - 1) then begin try Grid.InstantReadRecordEnter(AreaCell.Y + 1); NextRowIsSpecial := MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1; finally Grid.InstantReadRecordLeave; end; end; if (MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1) then begin Grid.Canvas.Pen.Color := clRed; Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right, ARect.Bottom)]); Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Right, ARect.Top), Point(ARect.Right, ARect.Bottom+1)]); if (AreaCell.X = 0) then Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Top), Point(ARect.Left, ARect.Bottom+1)]); end else if NextRowIsSpecial then begin Grid.Canvas.Pen.Color := clRed; Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right+1, ARect.Bottom)]); end; Processed := True; end; Демо проект прилагается. В Демо проекте в Unit2 приведен пример реализации окантовки через наследование грида.
|
Автор: | GoldMedium [ 04 мар 2021, 08:40 ] | ||
Заголовок сообщения: | Re: Отрисовка границ ячеек | ||
Просто фантастика!! Это то, что нужно. Спасибо Вам ОГРОМНОЕ!! Вы всегда находите решение и делаете это оперативно. Отличная поддержка. Единственный момент, можно ли задавать цвет границ для текущей строки (синим цветом на примере)? У меня остаются артефакты при перемещении к следующей строке.
|
Автор: | EhLibSupport [ 04 мар 2021, 16:17 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Добрый день. Чтобы ушли артефакты при перемещении на следующую строку необходимо перерисовывать весь грид. Добавьте следующее событие Код: procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin DBGridEh1.Invalidate; end; |
Автор: | GoldMedium [ 04 мар 2021, 21:28 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Добрый день. Это именно то, чего не хватало! Теперь всё работает именно так, как нужно. Надеюсь только, что постоянные вызовы DBGridEh1.Invalidate при переходе к следующий записи в гриде не сильно скажутся на скорости. Вы меня очень выручили. Спасибо вам БОЛЬШОЕ!! |
Автор: | GoldMedium [ 09 мар 2021, 20:39 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Добрый день. Вынужден снова обратиться к Вам за помощью. Всё отлично работает, благодаря Вам. Но есть нюанс: Цитата: а также возможность обращения к следующей записи грида для корректной отрисовки нижней линии для окантовки следующей ячейки. Чтобы обратить к следующей записи грида нужно, чтобы он был подключен через MemTableEh. В этом случае всё отлично работает. Но в нашем проекте очень много форм, где грид подключен напрямую к TFDQuery (FireDAC) и там прочитать значение следующей записи без изменения текущей (как в MemTableEh) нельзя. По-крайней мере, насколько мне известно. Чтобы добавить во все формы посредника в виде MemTableEh - это очень большой фронт работы и в разумные сроки сделать это нереально. Можно ли каким-то образом прочитать из грида значение заданной ячейки? Например, находясь в колонке 1 и строке 1 получить значение из колонки 1 и строки 2. При этом оставаясь в 1-й строке. Очень жду ответа. Спасибо Вам большое! |
Автор: | istrebitel [ 10 мар 2021, 02:39 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
бегать по датасету без генерации событий на свой страх и риск. |
Автор: | GoldMedium [ 10 мар 2021, 07:28 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
istrebitel писал(а): бегать по датасету без генерации событий на свой страх и риск. Причём здесь датасет. Цитата: ...прочитать из грида... К слову, и датасет датасету рознь. Где-то есть подобный функционал. Но это другая тема. Вопрос по-прежнему открытый. Из текущей строки без проблем получаю значение любой ячейки функцией: GetEditText(ACol, ARow: Longint) Но работает, к сожалению, только для текущей строки. |
Автор: | istrebitel [ 10 мар 2021, 09:16 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
GoldMedium писал(а): ...прочитать из грида... в гриде данных нет GoldMedium писал(а): К слову, и датасет датасету рознь. Где-то есть подобный функционал. Но это другая тема. Вопрос по-прежнему открытый. Этот функционал и есть стандартный, грид именно этим функционалом и бежит по датасету когда его отрисовывает. Код: procedure TCustomDBGridEh.DrawDataCell(ACol, ARow: Longint;
AreaCol, AreaRow: Longint; ARect: TRect; AState: TGridDrawState; CellAreaType: TCellAreaTypeEh); /// begin /// InstantReadRecordEnter(AreaRow); end. procedure TCustomDBGridEh.InstantReadRecordEnter(DataRowNum: Integer); var InstReadNode: TGroupDataTreeNodeEh; begin if ViewScroll then begin end else begin // всё что не MemTable (все остальные датасеты) FOldActiveRecord := DataLink.ActiveRecord; DataLink.ActiveRecord := DataRowNum; end; end; |
Автор: | GoldMedium [ 10 мар 2021, 09:36 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Спасибо Вам за участие и желание помочь. Я понимаю, что в гриде данных нет. Просто отчаянно ищу решение, чтобы избежать большого объёма работ. Дергать каждый раз при отрисовке датасет не лучшее решение |
Автор: | EhLibSupport [ 10 мар 2021, 15:04 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Если тип датасета не MemTableEh, то следующий обработчик события должен работать. Код: procedure TForm1.DBGridEh1Columns0AdvDrawDataCell(Sender: TCustomDBGridEh; Cell,
AreaCell: TGridCoord; Column: TColumnEh; const ARect: TRect; var Params: TColCellParamsEh; var Processed: Boolean); var Grid: TDBGridEhCrack; NextRowIsSpecial: Boolean; BottomLineIsDrawn: Boolean; LinesIsDrawn: Boolean; DataSet: TDataSet; OldActiveRecord: Integer; begin Grid := TDBGridEhCrack(Sender); DataSet := Grid.DataSource.DataSet; NextRowIsSpecial := False; if (DataSet.FieldByName('SpecialBorderState').AsInteger = 1) then begin Params.Background := $006DD3EB; Params.Font.Style := [fsBold]; end; Grid.DefaultDrawColumnDataCell(Cell, AreaCell, Column, ARect, Params); if (AreaCell.Y < Grid.InstantReadRecordCount - 1) then begin try //Grid.InstantReadRecordEnter(AreaCell.Y + 1); OldActiveRecord := Grid.DataLink.ActiveRecord; Grid.DataLink.ActiveRecord := AreaCell.Y + 1; NextRowIsSpecial := DataSet.FieldByName('SpecialBorderState').AsInteger = 1; finally //Grid.InstantReadRecordLeave; Grid.DataLink.ActiveRecord := OldActiveRecord; end; end; LinesIsDrawn := False; BottomLineIsDrawn := False; if (Params.Row = Grid.Row) or (Params.Row = Grid.Row - 1) then begin Grid.Canvas.Pen.Color := clBlue; if (Params.Row = Grid.Row) then begin Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right, ARect.Bottom)]); Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Right, ARect.Top), Point(ARect.Right, ARect.Bottom+1)]); if (AreaCell.X = 0) then Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Top), Point(ARect.Left, ARect.Bottom+1)]); LinesIsDrawn := True; BottomLineIsDrawn := True; end else begin Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right+1, ARect.Bottom)]); BottomLineIsDrawn := True; end; end; if (DataSet.FieldByName('SpecialBorderState').AsInteger = 1) and not LinesIsDrawn then begin Grid.Canvas.Pen.Color := clRed; if not (BottomLineIsDrawn) then Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right, ARect.Bottom)]); Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Right, ARect.Top), Point(ARect.Right, ARect.Bottom+1)]); if (AreaCell.X = 0) then Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Top), Point(ARect.Left, ARect.Bottom+1)]); end else if NextRowIsSpecial and not BottomLineIsDrawn then begin Grid.Canvas.Pen.Color := clRed; Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right+1, ARect.Bottom)]); end; Processed := True; end; |
Автор: | GoldMedium [ 10 мар 2021, 18:38 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Просто подарок! Всё отлично отрабатывает! Не представляете, как Вы меня выручили. Сэкономили мне вагон времени. Спасибо ВАМ большое!!! |
Автор: | Stalker4 [ 12 мар 2021, 07:48 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
GoldMedium писал(а): Добрый день. Чтобы добавить во все формы посредника в виде MemTableEh - это очень большой фронт работы и в разумные сроки сделать это нереально. Можно ли каким-то образом прочитать из грида значение заданной ячейки? Например, находясь в колонке 1 и строке 1 получить значение из колонки 1 и строки 2. При этом оставаясь в 1-й строке. FireDAC (FDQuery, FDMemTable) может как и MemTableEh перемещается по записям не меняя текущую позицию курсора Цитата: http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1008012&msg=21419431
TFDDatSRow есть запись. Объект создается для каждой записи. Скажем пробежаться по внутренностями TFDDataSet for i := 0 to FDQuery1.SourceView.Rows.Count - 1 do FDQuery1.SourceView.Rows[i].GetData(0); http://www.sql.ru/forum/actualutils.asp ... g=21513141 SourceView.Rows - с учетом фильтра и сортировки Table.Rows - без учета |
Автор: | GoldMedium [ 12 мар 2021, 10:30 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Большое спасибо, не знал. Это просто здорово Сравнил у себя скорость отрисовки границ при использовании Grid.DataLink.ActiveRecord и FDQuery1.SourceView.Rows[i].GetData(0). Оказалось, что вариант Grid.DataLink.ActiveRecord всегда чуть быстрее. Ненамного, но стабильно. Поэтому остановился пока на первом варианте. Но за подсказку большое спасибо, буду иметь ввиду |
Автор: | GoldMedium [ 12 мар 2021, 11:01 ] | ||
Заголовок сообщения: | Re: Отрисовка границ ячеек | ||
Что касается скорости, есть вопрос по перерисовке грида. В таблице с 12 колонками, у большинства из которых цвет фона и шрифта меняется в зависимости от значения ячейки, при прокрутке остаётся шлейф из линий, которым выделяется текущая строка. Grid.Invalidate выполняется в событии OnDataChange у DataSource. Вероятнее всего при прокрутке грид прорисоваться не успевает и сообщения Invalidate помещаются в очередь. Отсюда заметные артефакты на экране. С гридами, где меньше цветной раскраски, всё отрабатывает незаметно. Грид подключен через FDQuery
|
Автор: | EhLibSupport [ 12 мар 2021, 12:34 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Добрый день. Вместо DBGridEh.Invalidate; можно попробовать использовать DBGridEh.Repaint; Отрисовка должна происходить сразу, в коде Repaint. Но это может замедлить навигацию по гриду. |
Автор: | GoldMedium [ 12 мар 2021, 12:52 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
Добрый день. Спасибо, проверил. Не помогло, шлейф такой же. Пробовал добавить DBGridEh.Repaint ещё и в событие AfterScroll. Артефакты отрисовки без изменений. Вероятно, надо искусственно замедлять навигацию, чтобы грид успевал прорисоваться |
Автор: | GoldMedium [ 15 мар 2021, 08:52 ] |
Заголовок сообщения: | Re: Отрисовка границ ячеек |
В общем, кажется нашёл причину/решение артефактов при прокрутка своего грида. Причина была не в количестве колонок и их отрисовки, а банально в количестве контролов, связанных с тем же DataSource. У меня их было 15-20. Если у всех, кроме грида, обнулить DataSource - прокрутка выполняется быстро и без артефактов. Похоже нужно при прокрутке отключать обновление (DisableControls) всем контролам, кроме грида. Иначе Grid.Invalidate в событии TDataSource.OnDataChange просто не успевает |
Страница 1 из 1 | Часовой пояс: UTC |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |