Delphi TChart, TeeChart VCL – kliknięcie obrazka na wykresie, obsługa OnClick

Pytanie

W delphi możesz dodać na chart obrazek. Jak zrobić by obrazek wykonywał onclick?

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

  • Tak. Ponieważ obrazek narysowany na TChart nie jest „kontrolką” z własnym zdarzeniem, realizujesz „OnClick” przez przechwycenie kliknięcia na wykresie (np. OnMouseDown/OnClickMouse) i test trafienia punktu w prostokąt obrazka. Alternatywnie użyj nakładki TImage (Parent := Chart) lub narzędzia TeeChart TImageTool i również wykonaj test trafienia.
  • Kluczowe punkty:
    • Rysujesz obraz w OnAfterDraw lub korzystasz z TImage/TImageTool.
    • Zapamiętujesz jego TRect (pozycja/rozmiar).
    • W OnMouseDown wykresu sprawdzasz PtInRect(ImageRect, Point(X,Y)) i wywołujesz swoją akcję.

Szczegółowa analiza problemu

  • Kontekst: TChart (TeeChart VCL) renderuje całą zawartość na własnym Canvas. Elementy rysowane (bitmapy, grafika) nie mają własnych zdarzeń myszy. Dlatego obsługę kliknięcia implementujemy na poziomie zdarzeń wykresu, z własnym mapowaniem punktu myszy na obszar obrazka.
  • Trzy sprawdzone podejścia:
  1. Rysowanie na Canvas + test trafienia (uniwersalne, pełna kontrola)
  • Pole formularza:
    • FImage: TBitmap;
    • FImageRect: TRect;
  • Inicjalizacja (np. w FormCreate):
    • Załaduj FImage.
  • Rysowanie (po każdym odświeżeniu wykresu):
    • OnAfterDraw – wyznacz pozycję (np. prawy górny róg obszaru rysunku ChartRect) i narysuj.

Przykład:

private
  FImage: TBitmap;
  FImageRect: TRect;
procedure TForm1.FormCreate(Sender: TObject);
begin
  FImage := TBitmap.Create;
  FImage.LoadFromFile('icon.png'); // lub z zasobu
end;
procedure TForm1.Chart1AfterDraw(Sender: TObject);
var
  R: TRect;
  W, H, M: Integer;
begin
  // Pozycjonowanie względem obszaru rysunku (ChartRect)
  R := Chart1.ChartRect;  // obszar wykresu (bez osi/legendy)
  W := FImage.Width; H := FImage.Height; M := 8; // margines
  FImageRect := Rect(R.Right - W - M, R.Top + M, R.Right - M, R.Top + M + H);
  // Rysowanie
  if Assigned(FImage) and not FImage.Empty then
    Chart1.Canvas.StretchDraw(FImageRect, FImage);
end;
procedure TForm1.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if PtInRect(FImageRect, Point(X, Y)) then
  begin
    // "OnClick" obrazka
    ImageClicked;
    Exit; // opcjonalnie, aby nie propagować dalej
  end;
end;
procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if PtInRect(FImageRect, Point(X, Y)) then
    Chart1.Cursor := crHandPoint
  else
    Chart1.Cursor := crDefault;
end;
procedure TForm1.ImageClicked;
begin
  ShowMessage('Kliknięto obrazek na wykresie.');
end;

Uwagi:

  • Pozycjonuj względem ChartRect, aby obraz utrzymywał położenie względem obszaru danych przy zmianie rozmiaru.
  • Jeśli skalujesz obrazek, użyj StretchDraw z docelowym TRect dopasowanym do DPI/rozmiaru.
  1. Nakładka TImage jako dziecko wykresu (najszybsze w implementacji)
  • Tworzysz TImage z Parent := Chart1; ustawiasz Left/Top/Width/Height i Picture.
  • TImage ma własny OnClick – nic nie mapujesz.
  • Plusy: minimum kodu, pełna obsługa zdarzeń (OnClick, OnMouseEnter…).
  • Minusy: obraz nie „wie” o układzie wykresu (zoom/pan/ChartRect). To nakładka stała względem kontrolki, nie względem skali danych. Do ikon przy stałym ekranowym położeniu (np. „przycisk eksportu”) – idealne.

Przykład:

procedure TForm1.AddOverlayImage;
var
  Img: TImage;
begin
  Img := TImage.Create(Chart1);
  Img.Parent := Chart1;
  Img.AutoSize := True;
  Img.Picture.LoadFromFile('icon.png');
  Img.Left := Chart1.Width - Img.Width - 8;
  Img.Top  := 8;
  Img.Cursor := crHandPoint;
  Img.Transparent := True;
  Img.OnClick := procedure(Sender: TObject)
    begin
      ImageClicked;
    end;
end;
  1. TeeChart TImageTool (porządek w zasobach wykresu)
  • Dodajesz TImageTool do Chart1.Tools i wczytujesz grafikę (Bitmap/Picture).
  • Często brak bezpośredniego OnClick obrazka – używasz OnMouseDown wykresu + test trafienia w prostokąt obliczony z Left/Top i rozmiaru bitmapy narzędzia (analogicznie do metody 1).
  • Plusy: obraz żyje „w” wykresie (zależny od rysowania), spójne z narzędziami chartu.

Szkic:

uses TeEngine, TeeTools;
procedure TForm1.FormCreate(Sender: TObject);
var
  IT: TImageTool;
begin
  IT := TImageTool.Create(Chart1);
  IT.ParentChart := Chart1;
  IT.Bitmap.LoadFromFile('icon.png'); // lub IT.Picture.Assign(...)
  IT.Left := 12;  // współrzędne ekranowe w obrębie chartu
  IT.Top  := 12;
end;
procedure TForm1.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  i: Integer; IT: TImageTool; R: TRect;
begin
  for i := 0 to Chart1.Tools.Count - 1 do
    if Chart1.Tools[i] is TImageTool then
    begin
      IT := TImageTool(Chart1.Tools[i]);
      if Assigned(IT.Bitmap) and not IT.Bitmap.Empty then
      begin
        R := Rect(IT.Left, IT.Top, IT.Left + IT.Bitmap.Width, IT.Top + IT.Bitmap.Height);
        if PtInRect(R, Point(X, Y)) then
        begin
          ImageClicked;
          Break;
        end;
      end;
    end;
end;
  • Wariant alternatywny: TAnnotationTool z obrazem (Shape.Picture). W zależności od wersji TeeChart może oferować klik po adnotacji; jeśli nie – stosujesz identyczny test trafienia.

Teoretyczne podstawy:

  • Detekcja trafienia to porównanie punktu (X,Y) z obszarem obrazu (TRect). Dla obrazów skalowanych używamy prostokąta docelowego (nie rozmiaru natywnego bitmapy).
  • Pozycjonowanie względem ChartRect utrzymuje położenie względem zawartości wykresu (np. „przycisk” przypięty do rogu obszaru danych).

Praktyczne zastosowania:

  • Ikony narzędzi (eksport, reset zoom), logotypy, interaktywne legendy/filtry.

Aktualne informacje i trendy

  • W nowszych wydaniach TeeChart VCL utrzymano idiom: elementy rysowane (narzędzia, adnotacje) są obsługiwane przez zdarzenia wykresu i test trafienia. Część narzędzi (np. adnotacje) w niektórych edycjach posiada własne zdarzenia – sprawdź w Twojej wersji komponentów. Jeżeli potrzebujesz pełnych zdarzeń i układu ekranu – nakładka TImage pozostaje najszybszym sposobem.

Wspierające wyjaśnienia i detale

  • Różnica OnClick vs OnMouseDown: OnClick nie podaje X/Y w VCL TChart; do precyzyjnego testu używaj OnMouseDown (lub OnClickMouse, jeśli dostępne w Twojej wersji).
  • DPI/skalowanie: Jeśli aplikacja jest PerMonitorV2, przeliczaj docelowy rozmiar obrazka według bieżącego DPI (ScaleValue lub CurrentPPI/96) albo użyj StretchDraw do renderu w FImageRect wyznaczonym w pikselach ekranu.
  • Kolejność rysowania: Rysuj obraz po seriach (OnAfterDraw) – będzie „na wierzchu”. Dla nakładki TImage kolejność nie ma znaczenia (to osobna kontrolka).

Aspekty etyczne i prawne

  • Upewnij się, że masz prawa do używanego obrazka (licencja). W logotypach przestrzegaj wytycznych marki.

Praktyczne wskazówki

  • Zmień kursor na crHandPoint nad obrazkiem (OnMouseMove) – lepszy UX.
  • Dodaj „efekt hover” (np. narysuj lekki obrys) dla wizualnej odpowiedzi.
  • Jeżeli obrazek może nachodzić na elementy interaktywne wykresu (np. serię z OnClickSeries), po wykryciu trafienia możesz przerwać dalszą obsługę (Exit) lub dodać flagę „handled”.
  • Trzymaj pozycję/rozmiar w polach klasy; przeliczaj w OnAfterDraw i przy zmianie rozmiaru (OnResize -> Chart1.Invalidate).

Ewentualne zastrzeżenia lub uwagi dodatkowe

  • TImage jako nakładka nie „podąża” za zoom/pan osi. Jeśli obraz ma być związany z danymi (np. marker przy X,Y), musisz przeliczać pozycję przez konwersję wartości osi na piksele: Xp := Chart1.Axes.Bottom.CalcXPosValue(Xval); Yp := Chart1.Axes.Left.CalcYPosValue(Yval).
  • Nie wszystkie edycje TeeChart mają te same właściwości (Bitmap vs Picture) w TImageTool – dostosuj kod do swojej wersji.

Sugestie dalszych badań

  • Sprawdź narzędzia TeeChart: TAnnotationTool (Shape.Picture), TTextShape, oraz ewentualne zdarzenia kliknięcia tych obiektów w Twojej wersji.
  • Jeśli pracujesz w FMX: podejście podobne, ale z kontrolkami warstwowymi (TImage nad TChart) i skalowaniem w punktach logicznych.

Krótkie podsumowanie

  • Najbardziej uniwersalne: rysuj obrazek w OnAfterDraw i w OnMouseDown testuj PtInRect dla „OnClick” obrazka.
  • Najprostsze: nałóż TImage (Parent := Chart1) i obsłuż jego OnClick – dobre dla stałych ikon UI.
  • „Czyste” w TeeChart: TImageTool + test trafienia w OnMouseDown. Wszystkie trzy metody są produkcyjnie stosowane; wybór zależy od tego, czy obraz ma być przypięty do obszaru danych, do ekranu, czy ma żyć w kolekcji narzędzi wykresu.

Oceń odpowiedź:
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.

Zadaj dodatkowe pytanie Sztucznej Inteligencji

Czekaj (2min)...