От новичка до гуру: Курсы программирования на CyberDuff

Delphi Graphics32 рисует прозрачный эллипс на слое

Я хочу иметь возможность рисовать пустой эллипс на прозрачном слое в ImgView32. Любая идея, как это сделать? Пока все, о чем я могу думать, это:

 BL := TBitmapLayer.Create(ImgView.Layers);
    BL.Bitmap.DrawMode := dmTransparent;
    BL.Bitmap.SetSize(imwidth,imheight);
    BL.Bitmap.Canvas.Pen.Width := penwidth;
    BL.Bitmap.Canvas.Pen.Color := pencolor;
    BL.Location := GR32.FloatRect(0, 0, imwidth, imheight);
    BL.Scaled := False;
    BL.OnMouseDown := LayerMouseDown;
    BL.OnMouseUp := LayerMouseUp;
    BL.OnMouseMove := LayerMouseMove;
    BL.OnPaint := LayerOnPaint;

...
BL.Bitmap.Canvas.Pen.Color := clBlue;
BL.Bitmap.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
BL.Bitmap.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,FEndPoint.X, FEndPoint.Y); 

Начальная и конечная точки получаются в событиях мыши.

На самом деле я пытаюсь нарисовать динамический эллипс (по событиям мыши). Таким образом, задействованы события onMouseDown (LayerMouseDown), onMouseUp (LayerMouseUp) и OnMouseMove (LayerMouseMove). В качестве справки проверьте этот вопрос, он касается динамического рисования линии. Я хочу сделать то же самое, но с эллипсами вместо линий.

Итак, вместо AddLineToLayer у меня есть процедура AddCircleToLayer. Теперь события выглядят так:

procedure TForm5.SwapBuffers32;
begin
    TransparentBlt(
      BL.Bitmap.Canvas.Handle, 0, 0, BL.Bitmap.Width, BL.Bitmap.Height,
      bm32.Canvas.Handle, 0, 0, bm32.Width, bm32.Height, clWhite);
end;

procedure TForm5.ImgViewResize(Sender: TObject);
begin
  OffsX := (ImgView.ClientWidth - imwidth) div 2;
  OffsY := (ImgView.ClientHeight - imheight) div 2;
  BL.Location := GR32.FloatRect(OffsX, OffsY, imwidth+OffsX, imheight+OffsY);
end;

procedure TForm5.LayerMouseDown(Sender: TObject; Buttons: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FStartPoint := Point(X-OffsX, Y-OffsY);
  FDrawingLine := true;
end;

procedure TForm5.LayerMouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);
begin
  if FDrawingLine then
  begin
    SwapBuffers32;
      if RadioGroup1.ItemIndex=0 then
      begin
        BL.Bitmap.Canvas.Pen.Color := pencolor;
        BL.Bitmap.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
        BL.Bitmap.Canvas.LineTo(X-OffsX, Y-OffsY);
      end
      else
      begin
        BL.Bitmap.Canvas.Pen.Color := pencolor;
        BL.Bitmap.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
        SwapBuffers32;
        BL.Bitmap.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,X-OffsX, Y-OffsY);
      end;
  end;
end;

procedure TForm5.LayerMouseUp(Sender: TObject; Buttons: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
      if RadioGroup1.ItemIndex=0 then
      begin
        FDrawingLine := false;
        FEndPoint := Point(X-OffsX, Y-OffsY);
        AddLineToLayer;
        SwapBuffers32;
      end
      else
      begin
        FDrawingLine := false;
        FEndPoint := Point(X-OffsX, Y-OffsY);
        AddCircleToLayer;
        SwapBuffers32;
      end
end;

procedure TForm5.LayerOnPaint(Sender: TObject; Buffer: TBitmap32);
begin
  SwapBuffers32;
end;

procedure TForm5.AddLineToLayer;
begin
  bm32.Canvas.Pen.Color := pencolor;
  bm32.Canvas.Pen.Width := penwidth;
  bm32.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
  bm32.Canvas.LineTo(FEndPoint.X, FEndPoint.Y);
end;

procedure TForm5.AddCircleToLayer;
begin
  bm32.Canvas.Pen.Color := pencolor;
  bm32.Canvas.Pen.Width := penwidth;
  bm32.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
  bm32.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,FEndPoint.X, FEndPoint.Y);
  SwapBuffers32;
end;

Но когда я использую этот код, круг (эллипс) заполняется белым (как на этом изображении) введите описание изображения  здесь пока я не начну рисовать следующий эллипс (поэтому onMouseMove и onMouseUp эллипс заполняется). И только когда я делаю еще один onMouseDown, тогда предыдущий круг становится пустым, но новый эллипс также заполняется белым (как на этом изображении) введите здесь описание изображения

Также, если вы попытаетесь сделать больше эллипсов один за другим и поверх старых, вы заметите, что будут следы эллипсов onMouseMove, как на этом изображении:

введите здесь описание изображения

Так что должно быть что-то, что мне не хватает в этом коде.

Пожалуйста, помогите мне решить эту проблему.


  • Что ж, на самом деле ответ был довольно прост... установите кисть. Цвет на 0, прежде чем рисовать эллипс... Это делает эллипс пустым. Удивительно просто :) 18.02.2015
  • Установка Brush.Color на 0 фактически сделает его черным. Однако установка Brush.Style на bsClear должна помочь. 18.02.2015
  • Вы пробовали Brush.Style := bsClear? 23.02.2015

Ответы:


1

Если вы используете последний код GR32 из магистрали, вы также можете использовать этот фрагмент кода для определения эллипса.

Points := Ellipse(Center.X, Center.Y, Radius.X, Radius.Y);

или еще проще

Points := Ellipse(Center, Radius);

где Points определяется как

Points: TArrayOfFloatPoint;

Это создает многоугольник эллипса с центром в Center и независимым радиусом, связанным с x и y, определенным Radius.

Когда у вас есть полигон, вы можете визуализировать его с помощью любого векторного рендерера. Например, вы можете использовать встроенный визуализатор VPR с

PolygonFS(Bitmap, Points, SomeColor32);

чтобы отобразить заполненный эллипс.

Однако, если вы хотите отображать только кадр, вы можете использовать этот

PolylineFS(Bitmap, Points, AnotherColor32, True, PenWidth);

Параметры для этого

  1. Bitmap = экземпляр TBitmap32 для рендеринга
  2. Точки = точки многоугольника (как определено выше)
  3. AnotherColor32 = цвет, который используется для рендеринга
  4. True = замкнутый многоугольник (иначе ваш эллипс будет иметь зазор между начальной и конечной точкой
  5. PenWidth = Ширина кадра

Если хотите, вы также можете отобразить это за один вызов, например

PolylineFS(Bitmap, Ellipse(Center, Radius), AnotherColor32, True, PenWidth);

Чтобы получить произвольный (повернутый) эллипс, вам необходимо преобразовать многоугольник перед рендерингом. Ты можешь использовать

TransformPolygon(Points, Transformation);

для этого, который получает экземпляр TTransformation в качестве второго параметра. Это может включать в себя все распространенные операции, такие как поворот, наклон, масштабирование и перемещение.

Если вы используете это, вы также можете начать с более простого круга в качестве входного многоугольника и масштабировать круг, чтобы получить эллипс.

Приведенный выше код требует включения в ваш проект модулей GR32_VectorUtils, GR32_Polygons, например

uses
  GR32_VectorUtils, GR32_Polygons;

Преимущество заключается в том, что вы не полагаетесь на GDI для рендеринга, и поэтому вы можете выбрать средство рендеринга из доступных средств рендеринга из GR32. Некоторые из них включают эффект, подобный ClearType, и улучшают видимость на ЖК-экранах. Не говоря уже о качестве сглаживания и возможности управления гаммой для рендеринга.

18.02.2015
  • Ваш вклад всегда ценится CWBudde. Еще раз спасибо за настоящий подход Graphics32. Пожалуйста, уточните немного о выборе доступных рендереров. Например, если я хочу, чтобы кадр был более гладким? Как насчет управления гаммой, сглаживанием и четким типом? Я уверен, что и другие выиграют от этого. 20.02.2015
  • CWBudde, пожалуйста, взгляните и на этот вопрос: обычные слои со слоями рисования">stackoverflow.com/questions/28623999/ . Я мог бы использовать ваш вклад там ... 20.02.2015

  • 2

    Поэтому при рисовании круга/эллипса установите цвет кисти на 0, например:

    procedure TForm5.AddCircleToLayer;
    begin
      bm32.Canvas.Pen.Color := pencolor;
      bm32.Canvas.Pen.Width := penwidth;
      bm32.Canvas.Brush.Color := 0; // this here does the magic
      bm32.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
      bm32.Canvas.Ellipse(FStartPoint.X, FStartPoint.Y,FEndPoint.X, FEndPoint.Y);
      SwapBuffers32;
    end;
    

    Также сделайте то же самое в событии LayerMouseMove.

    17.02.2015
    Новые материалы

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

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

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

    Я предполагаю, что вы имеете в виду методы обработки категориальных данных.
    Я предполагаю, что вы имеете в виду методы обработки категориальных данных. Пожалуйста, проверьте мой пост Инструментарий специалиста по данным для кодирования категориальных переменных в..

    Игра в прятки с данными
    Игра в прятки с данными Я хотел бы, чтобы вы сделали мне одолжение и ответили на следующие вопросы. Гуглить можно в любое время, здесь никто не забивается. Сколько регионов в Гане? А как..