C++Builder
  Начало   Форум   Помощь Войти Регистрация  
Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Работаем с форматом Jpeg  (Прочитано 46008 раз)
VerZer
Участник
**

Сказали спасибо: +92/-10
Offline Offline

Сообщений: 1139


« Ответ #30 : 17 апреля 2008, 17:56:47 »

проблема в том, что ScrollBox не ловит фокус, при клике по нему.
внаглую можно решить так:
OnMouseMove
Код:
ScrollBox1->SetFocus();
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #31 : 17 апреля 2008, 21:14:18 »

Спасибо всем кто вместе со мной думал!

Проблема прокрутки решена самостоятельно  Смеющийся

Имеем код:

Код
void __fastcall TForm3::Image1MouseDown(TObject *Sender,
     TMouseButton Button, TShiftState Shift, int X, int Y)
{
  xx=X;
  yy=Y;    
}
//---------------------------------------------------------------------------
 
void __fastcall TForm3::Image1MouseMove(TObject *Sender, TShiftState Shift,
     int X, int Y)
{
 if(!Shift.Contains(ssLeft)) return;
 
  ScrollBox1->VertScrollBar->Position=ScrollBox1->VertScrollBar->Position+(yy-Y);
  ScrollBox1->HorzScrollBar->Position=ScrollBox1->HorzScrollBar->Position+(xx-X);
}

  • В первой функции (событие на нажатие кнопки мыши) запоминаем координаты нажатия левой кнопки мыши в глобальные переменные xx и yy.
  • Во второй функции (событие перемещения мыши) первым делом проверяем, нажата ли левая кнопка мыши, если нет, то выходим, если да то продолжаем работать. Дальше все просто, делается простое приращение к начальным координатам.
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #32 : 17 апреля 2008, 21:27:23 »

ВСЕМ

Осталась еще одна проблемка. Вот я загружаю картинку формата jpg в Image (как это делает указано где-то выше), ну а теперь как реализовать zoom in и zoom out с помощью билинейной интерполяции? можно и трилинейной, если кто-то знает как это.

Буду рад выслушать все Ваши мысли.

Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #33 : 21 апреля 2008, 13:04:24 »

Как динамически создавать объекты Image разобрано выше.

Следующий вопрос: Как теперь добавить обработку событий у этих объектов? Например двойной клик мыши. Неужели придется постоянно циклически перебирать их? а если объектов 300, или больше, тогда это все затянется.
Записан
oxotnik
Глобальный модератор
***

Сказали спасибо: +100/-15
Offline Offline

Сообщений: 2425


« Ответ #34 : 21 апреля 2008, 13:59:32 »

а в выше предложенной ссылке есть пример, как создвать много объектов а так же как присваивать им обработчик событий
(обработчик там один на всех, но ничего не мешает делать разные обработчики и на разные события)
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #35 : 21 апреля 2008, 21:25:55 »

To oxotnik

Реализовал обработчик события двойной клик:

Код
 
   ...
   //добавляю обработчик события двойной клик левой кнопкой
    Pict->OnDblClick=PictDblClick;
  ...
 

так как ты и говорил, это один обработчик на все объекты, а как реализовать обработчик события на каждый объект и потом обработать их?  Непонимающий мне это необходимо для того, чтобы я мог знать на каком из объектов пользователь сделал двойной клин. может быть существует и другое решение этой проблемы, с помощью одного обработчика, но как это сделать? подскажи, если в курсе.
Записан
oxotnik
Глобальный модератор
***

Сказали спасибо: +100/-15
Offline Offline

Сообщений: 2425


« Ответ #36 : 21 апреля 2008, 21:34:05 »

в событии OnClick входной параметр TObject *Sender - как раз и содердит конкретный элемент от которго событие и пришло...
ЗЫ в примере там про это тоже еть вроде (через dynamic_cast)
Записан
Admin
Администратор
***

Сказали спасибо: +22/-4
Offline Offline

Сообщений: 286


« Ответ #37 : 21 апреля 2008, 21:46:47 »

Также как вариант при создании присвоить им в свойство Tag целое число Pict->Tag= j++;
А потом проверять по значению этого свойства Tag. Иногда бывает полезно.

http://rxlib.ru/forums/index.php?act=ST&f=3&t=2138
Записан
oxotnik
Глобальный модератор
***

Сказали спасибо: +100/-15
Offline Offline

Сообщений: 2425


« Ответ #38 : 21 апреля 2008, 21:47:44 »

Также как вариант при создании присвоить им в свойство Tag целое число Pict->Tag= j++;
А потом проверять по значению этого свойства Tag. Иногда бывает полезно.
там все в map-у сыплется... индекс уже есть
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #39 : 22 апреля 2008, 17:31:42 »

To Admin

Твой вариант не подходит, потому что заранее не известно сколько будет объектов, следовательно цикл не применим, а switch тем более. Картинок может быть и 1000, это что же, каждый раз перебирать цикл из 1000 компонентов? Я считаю это не самый лучший вариант, хотя имеет место для существования.

To oxotnik
 
Потыкался я с объектом Sender, не могу взять в толк, какая из его функций возвращает элемент на котором было произведено событие. В твоем примере я ничего подобного не нашел. Можешь подсказать что не так? или может вырезку кода подкинешь, где это реализовано, сам я что-то не могу разобраться.
Записан
oxotnik
Глобальный модератор
***

Сказали спасибо: +100/-15
Offline Offline

Сообщений: 2425


« Ответ #40 : 22 апреля 2008, 17:55:29 »

при динамическом создании компонента задаешь ему событие:
Код
  dynBtn = new TButton(this);
 btnMap[btnCounter] = dynBtn;
 dynBtn->OnClick =  DynBtnClick;
 
сама ф-я события:
Код
в *.hpp
class TForm1 : public TForm
{
...
private:
       void __fastcall DynBtnClick(TObject *Sender);
....
};
 
в *.срр
void __fastcall TForm1::DynBtnClick(TObject *Sender)
{
TButton *btn = dynamic_cast<TButton*>(Sender);
ShowMessage (btn->Name);
}
 
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #41 : 22 апреля 2008, 17:57:38 »

to Admin и oxotnik

Спасибо Вам обоим!  Смеющийся ,  сам немного ступил.
Взяв напутствие от oxotnik , про dynamic_cast, и внимательно проштудировав еще раз код Admina в результате получил код, который выдает имя объекта, на котором произошло событие. Ну а так как у меня картинки грузятся по порядку, в созданные динамически Image, то дальше не трудно найти и имя загруженной картинки в Image.

В итоге имеем код (собранный воедино):

в заголовочном файле объявляем функцию реакции на двойной клик

Код
void __fastcall PictDblClick(TObject *Sender);

тут же динамические объекты
Код
        map <int, TImage*> ImMap; //отображение
                      TImage *Pict;                    //собственно Image                
 


далее код:

Код
  for(int i=0;i<k;i++) //к- это количество картинок
  {
    Pict = new TImage (this);
    //родители
    Pict->Parent =ScrollBox1;
    ....
    Pict->Name = "Image_" + IntToStr(i);//имя очередного созданного Image
    //загрузка картинки
    Pict->Picture->LoadFromFile(IntToStr(i+1)+".jpg");
    ....
    //добавляю обработчик события двойной клик левой кнопкой
    //обработчик получается один на все элементы
    Pict->OnDblClick=PictDblClick;
    //засовываю все в отображение
    ImMap[i]=Pict;
  }

и, собственно сама функция обработки клика:

Код
void __fastcall TForm2::PictDblClick(TObject *Sender)
{
 TImage *im = dynamic_cast<TImage*>(Sender); // преобразование в нужный обьект
 ShowMessage(im->Name); //вывод на экран имени Image на котором сделан двойной клик
}
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #42 : 22 апреля 2008, 17:59:10 »

Еще раз Спасибо oxotnik, мы с тобой практически одновременно писали сообщения. Улыбка
Записан
AVC
Администратор
***

Сказали спасибо: +28/-6
Offline Offline

Сообщений: 1189


« Ответ #43 : 23 апреля 2008, 09:11:08 »

Код:
void __fastcall TForm2::PictDblClick(TObject *Sender)
{
  TImage *im = dynamic_cast<TImage*>(Sender); // преобразование в нужный обьект
  ShowMessage(im->Name); //вывод на экран имени Image на котором сделан двойной клик
}
(Имхо)
Я уже как то писал: использование dynamic_cast без проверки бессмысленно и равносильно явному преобразованию. Поэтому лучше так
Код:
void __fastcall TForm2::PictDblClick(TObject *Sender)
{
  TImage *im = dynamic_cast<TImage*>(Sender); // преобразование в нужный обьект
  if (!im) return;
  ShowMessage(im->Name); //вывод на экран имени Image на котором сделан двойной клик
}
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #44 : 23 апреля 2008, 12:22:07 »

Согласен с AVC, проверка необходима всегда.  Улыбка
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #45 : 24 апреля 2008, 15:53:11 »

Вот мы создали динамически n-ое количество объектов Image, загрузили в каждый из них по картинке jpg, обработали событие двойной клик. А как теперь обработать такое событие, чтобы при нахождении мышки над каким-либо объектом Image, вокруг него рисовалась рамка, чтобы было понятно, какой из объектов под курсором? При уходе курсора с этого объекта, рамка бы исчезала.

Облазил форум, но ничего подходящего не нашел.

Может кто сталкивался с такой проблемой?  Грустный
Записан
VerZer
Участник
**

Сказали спасибо: +92/-10
Offline Offline

Сообщений: 1139


« Ответ #46 : 24 апреля 2008, 15:56:56 »

OnMouseMove
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #47 : 24 апреля 2008, 16:04:03 »

OnMouseMove это когда мышка двигается над компонентом, и это понятно. Не понятно как все это убрать (рамку), когда мышка покинет поле объекта. ?
Записан
VerZer
Участник
**

Сказали спасибо: +92/-10
Offline Offline

Сообщений: 1139


« Ответ #48 : 24 апреля 2008, 16:16:29 »

скомпоновать с OnMouseMove родителя:
в OnMouseMove картинки узнаём, вокруг какой рисовать рамку
в OnMouseMove ридителя рисуем, если курсор над картинкой
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #49 : 24 апреля 2008, 18:24:02 »

To VerZer

Реализовал я то что ты написал. Событие доходит туда, куда нужно. Выводил через ShowMessage номер картинки, на котором была мышь, все работает. Теперь не получается отрисовать рамку. Пробую рисовать вот так :

Код
ImMap[inum]->Picture->Bitmap->Canvas->FrameRect(Rect(1,1,ImMap[inum]->Width-1,ImMap[inum]->Height-1));

ImMap - это отображение, в котором находятся объекты Image.

только ошибку выдает. (в это динимический Image загружена картинка jpg через LoadFromFile). В чем может быть проблема?
Записан
AVC
Администратор
***

Сказали спасибо: +28/-6
Offline Offline

Сообщений: 1189


« Ответ #50 : 24 апреля 2008, 18:41:35 »

http://cbuilder.ru/index.php/topic,557.msg3174.html#msg3174
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #51 : 24 апреля 2008, 19:40:15 »

To AVC

Этот вариант не приемлим. Потому что мы можем иметь картинки и по 5 мегабайт (картинки формата jpg находятся в файлах), а картинок на форме 50, и если пользователь переместить мышку слева направо быстро, то произойдет много событий, при которых нужно будет несколько раз загружать картинки большого объема, будет очень тормозить. У меня и так, если картинки некоторые большие, то предпросмотр долговато подгружает картинки, а в твое варианте таких подгрузок будет гораздо больше.
Думаю есть вариант поизящней, без повторных загрузок картинок. Нужно всего лишь нарисовать рамку вокруг картинки, и потом ее стереть, вот и все.
Твой вариант приемлим при небольших объемах файлов, а еще лучше если они в ресурсах.
Записан
AVC
Администратор
***

Сказали спасибо: +28/-6
Offline Offline

Сообщений: 1189


« Ответ #52 : 25 апреля 2008, 10:05:33 »

Ну нет, так нет, тем более это не моё решение. Я просто вспомнил такую тему.
Хотя обшую схему считаю правильной
Добавить поддержку событий мыша MouseLeave (сообщение CM_MOUSELEAVE) и MouseEnter (сообщение CM_MOUSEENTER).
А уж как обрабатыватьэти сообщения и что при этом перерисовывать - дело хозяйское.
Записан
oxotnik
Глобальный модератор
***

Сказали спасибо: +100/-15
Offline Offline

Сообщений: 2425


« Ответ #53 : 25 апреля 2008, 10:52:30 »

размещаем картинки на TPanel
в свойствах панели:
BevelIner = bvNone;
BevelOuter = bvNone;
а при перемещениях мыши меняется
BorderStyle c bsNone (курсок не над панелью) на bsSingle (курсор над панелью)
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #54 : 25 апреля 2008, 11:34:41 »

To oxotnik

Сделал я вот так (только расположены картинки у меня не на панели а на ScrollBox, потому что когда их много, добавляется полоса прокрутки, все остальное также):

в обработчике событий движения мыши на ScrollBox

Код
void __fastcall TForm2::ScrollBox1MouseMove(TObject *Sender,
     TShiftState Shift, int X, int Y)
{
 ScrollBox1->BorderStyle=bsSingle;
}

в обработчике событий движения мыши на Image (они то у меня динамические)
Код
void __fastcall TForm2::PictMouseMove (TObject *Sender,TShiftState Shift, int X, int Y)
{
 ScrollBox1->BorderStyle=bsNone;
}


в итоге получается что весь экран дергается. ничего не выделяется в общем.


Хотя твоя идея мне понравилась. Я подумал, а ведь можно при попадании курсора на Image отрисовывать вокруг него рамку, и запоминать в какой-нить переменной, над которым Image  мы ее нарисовали. Потом когда курсор попадает на ScrollBox (он родитель моих картинок) стирается рамка над той картинкой, которая хранится в созданной нами переменной, цветом ScrollBox-а. Как думаешь, подойдет такой способ? еще думаю добавить переменную типа bool чтобы по несколько раз не зарисовывать рамку,зарисовали раз, и все.

У меня только не получается нарисовать прямоугольник заданного цвета в Image где уже есть картинка. Подскажи как это сделать, а остальное я сам попробую.  Непонимающий
Записан
oxotnik
Глобальный модератор
***

Сказали спасибо: +100/-15
Offline Offline

Сообщений: 2425


« Ответ #55 : 25 апреля 2008, 11:40:18 »

во первых: перепутал когда надо рисовать рамку и когда не надо
во вторых: зачем применять BorderStyle это для ScrollBox1 (я говорил про панели на которых картинка, ты же определенную картинку хочешь выделять)
в третьих: дабы не дергалось и ситема не грузилась, проверяй значение BorderStyle и если оно не соответсвует нужному только тогда применяй

Код
void __fastcall TForm1::Panel1MouseMove(TObject *Sender, TShiftState Shift,
     int X, int Y)
{
 if (Panel1->BorderStyle != bsSingle)Panel1->BorderStyle = bsSingle;
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
     int X, int Y)
{
 if (Panel1->BorderStyle != bsNone)Panel1->BorderStyle = bsNone;
}
 
вот так у меня ничего не тормозит (правда только для одной панельки, а если их много и динамические тогда надо обрабатывать сообщение MOUSELEAVE как подсказал AVC)
Записан
Nikita
Участник
**

Сказали спасибо: +6/-1
Offline Offline

Сообщений: 476


« Ответ #56 : 25 апреля 2008, 14:29:27 »

Благодарю всех за советы! Заработало так как надо  Смеющийся

Имее код:

Код
 for(int i=0;i>k;i++) //к- это количество картинок
  {
 
    Pict = new TImage (this);
    Panel= new TPanel (this);
    //родители
 
    Panel->Parent=ScrollBox1;
    Pict->Parent=Panel;
 
 
    Panel->Name="Panel_"+ IntToStr(i);
    Pict->Name = "Image_" + IntToStr(i);
    //номер картинки (вспомогательный параметр)
    Pict->Tag=i+1;
    //ширина и высота картинки, соответственно
    Pict->Width = w;
    Pict->Height = h;
 
    Panel->Caption="";
    Panel->Width=w;
    Panel->Height=h;
 
    Panel->Top=....;//тут каждый пишет свои координаты Panel
    Panel->Left=....;//это координаты Panel на которой будет картинка
                          //координаты Pict не нужны так как она привязана теперь к Panel
 
    Panel->BevelInner=bvNone;
    Panel->BevelOuter=bvNone;
 
    Pict->Stretch=true;
    Pict->Proportional=true;
    Pict->Center;
    ....
    //загрузка картинки
     Pict->Picture->LoadFromFile(Form1->tmpdir+"\\datatemp"+IntToStr(i+1)+".jpg");
    ....
 
    //добавляю обработчик события перемещение мышки на объекте
    Pict->OnMouseMove=PictMouseMove;
 
    ImMap[i]=Pict;     //отображение хранящее картинки
    ImPanel[i]=Panel; //отображение зранящее Panel
    ....
  }

Далее в обработчике события перемещения мыши на картинке пишем:

Код
void __fastcall TForm2::PictMouseMove (TObject *Sender,TShiftState Shift, int X, int Y)
{
//узнаем, какую картинку выделять
 TImage *im = dynamic_cast<TImage*>(Sender); // преобразование в нужный обьект
 if (!im) return; //проверка на валидность
 inum=im->Tag-1; //во вспомогательной переменной хранится номер картинки
  //собственно условие, выделять
  if (ImPanel[inum]->BorderStyle != bsSingle)ImPanel[inum]->BorderStyle = bsSingle;
}

в переменной inum (глобальная) мы сохраняем номер картинки, на которой находится курсор, а этот номер соответствует номеру Панельки, на которой нарисована картинка.

теперь если курсор мыши находится на ScrollBox, то обрабатываем событие перемещения мыши на ScrollBox, это событие и убирает выделение:

Код
void __fastcall TForm2::ScrollBox1MouseMove(TObject *Sender,
     TShiftState Shift, int X, int Y)
{
if (ImPanel[inum]->BorderStyle != bsNone) ImPanel[inum]->BorderStyle = bsNone;
}

Все лишнее я убрал.

Код полностью рабочий.

По моему почучилось все очень даже изящно, и самое главное никаких файлов больше подгружать не надо.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в: