Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Графика и игры
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 24.05.2013, 01:01
Аватар для kaktusad
kaktusad kaktusad вне форума
Прохожий
 
Регистрация: 16.11.2012
Сообщения: 18
Репутация: 10
По умолчанию Движение прямоугольника вместе с мышкой

Вопрос, думаю, очень легкий, но прошу мне помочь, не могу ни как разобраться.
Есть компонент PaintBox, на котором размещена картинка. Нужно сделать, чтобы при передвижении указателя мышки по пэнинтбоксу вместе с ним и двигался прямоугольник, например, зеленый 40х40.
У меня проблема возникает в том, что при передвижении указателя нужно рисовать новый прямоугольник и стирать старый, но чтобы весь рисунок не перерисовывать, так как приложение подвисает. Рисовать прямоугольник пытался с помощью канвы...
Ответить с цитированием
  #2  
Старый 24.05.2013, 01:55
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Рисуй на буферном битмапе, а в событии OnPaint PaintBox-а копируй битмап в канву PaintBox-а.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #3  
Старый 24.05.2013, 01:59
Аватар для kaktusad
kaktusad kaktusad вне форума
Прохожий
 
Регистрация: 16.11.2012
Сообщения: 18
Репутация: 10
По умолчанию

Цитата:
Сообщение от angvelem
Рисуй на буферном битмапе, а в событии OnPaint PaintBox-а копируй битмап в канву PaintBox-а.
Так все равно же при каждом движении мышки придется перерисовывать битмап?
Ответить с цитированием
  #4  
Старый 24.05.2013, 02:06
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Выод битмапа на канву PaintBox-а вызовет меньше перерисовок, чем непосредственное рисование на канве самого PaintBox-а
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #5  
Старый 24.05.2013, 10:21
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Цитата:
Сообщение от kaktusad
Так все равно же при каждом движении мышки придется перерисовывать битмап?
А думаешь графические редакторы делают как-то по другому?
Ответить с цитированием
  #6  
Старый 24.05.2013, 11:31
Аватар для Freeman
Freeman Freeman вне форума
Местный
 
Регистрация: 05.10.2012
Адрес: Санкт-Петербург
Сообщения: 577
Версия Delphi: 6
Репутация: выкл
По умолчанию

Цитата:
Сообщение от kaktusad
нужно рисовать новый прямоугольник и стирать старый, но чтобы весь рисунок не перерисовывать, так как приложение подвисает.
Рисуй в режиме XOR:
Код:
type
  TMainForm = class(TForm)
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    FPrevX, FPrevY: Integer;
  end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FPrevX := -1;
  FPrevY := -1;
end;

procedure TMainForm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  with TPaintBox(Sender).Canvas do
  begin
    with Brush do
    begin
      Color := clTeal;
      Style := bsSolid;
    end;
    with Pen do
    begin
      Color := clYellow;
      Mode := pmXor;
    end;
    if (FPrevX > 0) and (FPrevY > 0) then
      Rectangle(FPrevX - 10, FPrevY - 8, FPrevX + 10, FPrevY + 8);
    Rectangle(X - 10, Y - 8, X + 10, Y + 8);
  end;
  FPrevX := X;
  FPrevY := Y;
end;
Ответить с цитированием
  #7  
Старый 24.05.2013, 15:33
Аватар для kaktusad
kaktusad kaktusad вне форума
Прохожий
 
Регистрация: 16.11.2012
Сообщения: 18
Репутация: 10
По умолчанию

Freeman, вот что получилось


Изображение рисую на Пэинт боксе с помощью StretchDraw и если его перерисовывать при каждом движении мышки, то будут почти одни полосы.

Последний раз редактировалось kaktusad, 24.05.2013 в 15:36.
Ответить с цитированием
  #8  
Старый 24.05.2013, 19:10
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,723
Репутация: 52347
По умолчанию

А где именно вы изображение рисуете? В каком событии?
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #9  
Старый 24.05.2013, 19:47
Аватар для kaktusad
kaktusad kaktusad вне форума
Прохожий
 
Регистрация: 16.11.2012
Сообщения: 18
Репутация: 10
По умолчанию

Цитата:
Сообщение от Страдалецъ
А где именно вы изображение рисуете? В каком событии?
PaintBox.OnPaint
Ответить с цитированием
  #10  
Старый 25.05.2013, 08:17
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,096
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от kaktusad
Freeman, вот что получилось
...
Изображение рисую на Пэинт боксе с помощью StretchDraw и если его перерисовывать при каждом движении мышки, то будут почти одни полосы.

Ну, для особо извращенцев могу посоветовать вариант с запоминанием фона. Т.е. сначала отрисовываешь запомненный ранее фон (твоего размера, 40х40, если не ошибаюсь), потом меняешь координаты, запоминаешь по новым координатам фон, потом отрисовываешь свой квадрат. Ну и сначала при следующем перемещении мышы.

А вообще, вывод из буфферного битмапа на канву PaintBox занимает микроскопическое время, при включенном DoubleBuffered ничего не моргает. Только там есть маленький фокус - фон стирать не надо, надо сделать так, что бы картинка выводилась из буфера за одну операцию без стирания фона. Проверял на 8-мегапиксельных картинках. В твоем случае нужно будет 2 буфера. В первом лежит орининальная картинка, во втором ты подготавливаешь картинку для вывода и потом ее отрисовываешь на канве PaintBox.
Ответить с цитированием
  #11  
Старый 25.05.2013, 11:04
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Думается ТС нужен код для понимания сути процесса. Я уже пытался ему сказать про буферный битмап, но он не принял во внимание. Рисовать в OnPaint-е, полное извращение, будет постоянное дёрганье.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #12  
Старый 25.05.2013, 16:54
Аватар для kaktusad
kaktusad kaktusad вне форума
Прохожий
 
Регистрация: 16.11.2012
Сообщения: 18
Репутация: 10
По умолчанию

Цитата:
Сообщение от angvelem
Думается ТС нужен код для понимания сути процесса. Я уже пытался ему сказать про буферный битмап, но он не принял во внимание. Рисовать в OnPaint-е, полное извращение, будет постоянное дёрганье.
Можно по-подробней о сути буферного битмапа? И на чем тогда рисовать?
Ответить с цитированием
  #13  
Старый 13.06.2013, 18:51
Fatze Fatze вне форума
Прохожий
 
Регистрация: 13.06.2013
Сообщения: 2
Версия Delphi: Delphi 2009
Репутация: 10
По умолчанию Одно из решений

Код:
unit Unit2;

interface

  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, pngimage;

  type
    TForm2 = class(TForm)
      PaintBox1: TPaintBox; // Не забыть положить на форму и создать 2 обработчика
      procedure PaintBox1Paint(Sender: TObject);
      procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
      private
        { Private declarations }
      public
        { Public declarations }
    end;

  var
    Form2: TForm2;

implementation

{$R *.dfm}
const          //Graphics.pas
  Colors: array[0..19] of TIdentMapEntry = (
    (Value: clBlack; Name: 'clBlack'),
    (Value: clMaroon; Name: 'clMaroon'),
    (Value: clGreen; Name: 'clGreen'),
    (Value: clOlive; Name: 'clOlive'),
    (Value: clNavy; Name: 'clNavy'),
    (Value: clPurple; Name: 'clPurple'),
    (Value: clTeal; Name: 'clTeal'),
    (Value: clGray; Name: 'clGray'),
    (Value: clSilver; Name: 'clSilver'),
    (Value: clRed; Name: 'clRed'),
    (Value: clLime; Name: 'clLime'),
    (Value: clYellow; Name: 'clYellow'),
    (Value: clBlue; Name: 'clBlue'),
    (Value: clFuchsia; Name: 'clFuchsia'),
    (Value: clAqua; Name: 'clAqua'),
    (Value: clWhite; Name: 'clWhite'),

    (Value: clMoneyGreen; Name: 'clMoneyGreen'),
    (Value: clSkyBlue; Name: 'clSkyBlue'),
    (Value: clCream; Name: 'clCream'),
    (Value: clMedGray; Name: 'clMedGray'));




  procedure TForm2.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    const
      dx = 10;
      dy = 10;
    var
      MouseRect: Trect;
      MousePositionInParentCoordinates:TPoint;
    begin
      MousePositionInParentCoordinates:= PaintBox1.ClientToParent(Point(X, Y));     //Получаем смещение PaintBox относительно родительского оконного компонента
       // Формируем размеры прямоугольника под мышью
      MouseRect:=Rect(MousePositionInParentCoordinates,MousePositionInParentCoordinates);         // Прямоугольник в 0пикселов но в правильных координатах
      Windows.InflateRect(MouseRect,dx*2,dy*2);      // Растягиваем прямаугольник
      Windows.InvalidateRect(PaintBox1.Parent.Handle,MouseRect,True);      // Просим пометить как "Не валидную" область прямоугольника у родительского оконного компонента (Т.к. PaintBox не оконный компонент )
    end;

  procedure TForm2.PaintBox1Paint(Sender: TObject);
    var
      Priamougolnic: Trect;
    begin
      Priamougolnic := PaintBox1.BoundsRect; // <-размер холста

      PaintBox1.Canvas.Brush.Color := Colors[Random(Length(Colors)-1)].Value; //установка цвета заливки
      // в данном примере устанавливается случайный цвет из массива Colors и
      PaintBox1.Canvas.Rectangle(Priamougolnic);        // здесь можно рисовать фоновую картинку        а ПОТОМ картинку прямоугольника
      //закрашивается вся область холста. Сделано чтобы продемонстрировать что даже если рисовать всю картинку
      //перерисуется только помеченная нами как "НЕ ВАЛИДНАЯ"(испорченная) область холста
      // вывод если рисовать сначала всю картинку а потом текущее положение прямоугольника под мышью
      // мерцания будут заметны только при очень большом прямоугольнике под мышью
      // если заменить рисование копированием (при сложных картинках) мерцания будет меньше
      //Canvas.CopyRect
    end;

end.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:05.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025