В статье будет рассмотрен процесс разработки компонента "Светодиод" в среде Delphi XE10.1, а также способы устранения распространенных ошибок, с которыми могут столкнуться разработчики при создании пользовательских компонентов.
Описание проблемы
При разработке компонента "Светодиод" в Delphi XE10.1 пользователь столкнулся с ошибкой, при которой среда разработки (IDE) закрывалась при попытке использования созданного компонента в новом проекте. Проблема была обнаружена после закрытия IDE и последующего открытия его для нового проекта, где при добавлении компонента происходил сбой. Пользователь предоставил исходный код компонента, который ранее работал корректно.
Анализ кода
Исходный код компонента TZaxLED включает в себя приватные и опубликованные свойства, а также переопределенные методы Paint, Create и SetBounds. Основная логика отрисовки светодиода реализована в методе Paint. Однако, после внесения изменений в методы SetColorOn и SetColorOff, которые были обнулены до простых присваиваний без проверки статуса и вызова перерисовки, возникли новые проблемы, включая отсутствие изменения цвета светодиода как в дизайнере, так и во время выполнения.
Подтвержденный ответ
После тщательного анализа кода и комментариев пользователя, можно выделить несколько ключевых моментов:
В коде присутствует бесконечный цикл присваиваний в методах SetColorOn и SetColorOff, что приводит к ошибке "Stack Overflow".
Необходимо вызывать метод Invalidate после изменения свойств, влияющих на внешний вид компонента, чтобы инициировать перерисовку.
Свойство Color в классе TZaxLED избыточно, так как уже есть наследованное свойство Color от TGraphicControl.
Исправление кода
Для исправления ошибки и обеспечения корректной работы компонента, необходимо внести следующие изменения:
Удалить избыточное свойство Color.
Убрать бесконечные циклы присваиваний в методах SetColorOn и SetColorOff.
Добавить вызов Invalidate для перерисовки компонента после изменения свойств ColorOn, ColorOff и Status.
Очистить список использованных единиц (uses) в разделе interface, оставив только те, которые действительно используются.
Вот пример исправленного кода:
unit ZaxLED;
interface
uses
Classes, Controls, Graphics;
type
TZaxLED = class(TGraphicControl)
private
FColorOn: TColor;
FColorOff: TColor;
FStatus: Boolean;
FOnChange: TNotifyEvent;
procedure SetColorOn(Value: TColor);
procedure SetColorOff(Value: TColor);
procedure SetStatus(Value: Boolean);
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
property Width default 17;
property Height default 17;
property Align;
property Anchors;
property Constraints;
property ColorOn: TColor read FColorOn write SetColorOn default clLime;
property ColorOff: TColor read FColorOff write SetColorOff default clGray;
property Status: Boolean read FStatus write SetStatus default False;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
procedure Register;
implementation
uses
Math;
procedure Register;
begin
RegisterComponents('Samples', [TZaxLED]);
end;
constructor TZaxLED.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FColorOn := clLime;
FColorOff := clGray;
FStatus := False;
Width := 17;
Height := 17;
end;
procedure TZaxLED.Paint;
var
Radius, xCenter, YCenter: Integer;
begin
if csDesigning in ComponentState then
begin
Canvas.Pen.Style := psDot;
Canvas.Brush.Style := bsClear;
Canvas.Rectangle(ClientRect);
end
else
begin
if FStatus then
Canvas.Brush.Color := FColorOn
else
Canvas.Brush.Color := FColorOff;
Radius := Floor(Width / 2) - 2;
xCenter := Floor(Width / 2);
YCenter := Floor(Height / 2);
Canvas.Ellipse(xCenter - Radius, YCenter - Radius, xCenter + Radius, YCenter + Radius);
end;
end;
procedure TZaxLED.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
if AutoSize and (Align in [alNone, alCustom]) then
begin
AWidth := Width;
AHeight := Height;
end;
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;
procedure TZaxLED.SetColorOn(Value: TColor);
begin
if FColorOn <> Value then
begin
FColorOn := Value;
if FStatus then
Invalidate;
end;
end;
procedure TZaxLED.SetColorOff(Value: TColor);
begin
if FColorOff <> Value then
begin
FColorOff := Value;
if not FStatus then
Invalidate;
end;
end;
procedure TZaxLED.SetStatus(Value: Boolean);
begin
if Value <> FStatus then
begin
FStatus := Value;
Invalidate;
if Assigned(FOnChange) then
FOnChange(Self);
end;
end;
end.
Заключение
При разработке пользовательских компонентов важно тщательно проверять логику обработки событий и перерисовки. Исправление ошибок, связанных с бесконечными циклами и отсутствием перерисовки, позволит создать надежный компонент, который будет работать стабильно в среде Delphi XE10.1.
В статье рассматривается разработка компонента 'Светодиод' в среде Delphi XE10.1 и способы устранения ошибок при создании пользовательских компонентов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.