Перейти к содержанию
Fire Monkey от А до Я
  • 0

Не удается перетащить (Drag and Drop) итем TListBoxItem между двумя TListBox


vovanse

Вопрос

Delphi XE6. Пытаюсь реализовать Drag and Drop между двумя TListBox, но как-то безуспешно. А TTreeView, работает.

У принимающего TListBox вызываются только OnDragOver, OnDragEnter, OnDragLeave. А события OnDragChange, OnDragDrop - нет.

 

DragMode установлен в dmManual, AllowDrag пробовал и True и False. В обработчике DragOver Operation:=TDragOperation.Copy (другие варианты тоже пробовал)

 

Использовал в качестве принимающего TText, OnDragDrop прекрасно работает.

 

Пробовал и с созданными ListBoxItem и без них.

 

В чем может быть проблема? Или это пока не совсем работает? Как можно обойти?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Администраторы

  • Ставим TListBox.AllowDrag = True для источника итемов. С которого будем перетаскивать итемы в другой.
  • В обработчике TListBox.OnDragOver у приемника пишем:

    procedure TForm1.ListBox1DragOver(Sender: TObject; const Data: TDragObject; const Point: TPointF;
      var Operation: TDragOperation);
    begin
      Operation := TDragOperation.Copy;// или Move
    end;
    
  • Пишем обработчик TListBox.OnDragDrop для списка приемника:

    procedure TForm1.ListBoxDestinationDragDrop(Sender: TObject; const Data: TDragObject; const Point: TPointF);
    begin
      if Data.Source is TFmxObject then
        TFmxObject(Data.Source).Parent := ListBoxDestination;
    end;
    

Запускаем и смотрим.

post-1-0-27483500-1409086513.pngpost-1-0-39358500-1409086513.pngpost-1-0-52255200-1409086513.png

Ссылка на комментарий
  • 0

Собственно так я и делал. Но только не работает. Не вызывается ListBoxDestinationDragDrop.

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
  FMX.ListBox, FMX.Layouts;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    ListBox2: TListBox;
    ListBoxItem1: TListBoxItem;
    ListBoxItem2: TListBoxItem;
    ListBoxItem3: TListBoxItem;
    ListBoxItem4: TListBoxItem;
    ListBoxItem5: TListBoxItem;
    ListBoxItem6: TListBoxItem;
    procedure ListBox1DragOver(Sender: TObject; const Data: TDragObject;
      const Point: TPointF; var Operation: TDragOperation);
    procedure ListBox1DragDrop(Sender: TObject; const Data: TDragObject;
      const Point: TPointF);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.ListBox1DragDrop(Sender: TObject; const Data: TDragObject;
  const Point: TPointF);
begin
  if Data.Source is TFmxObject then
    TFmxObject(Data.Source).Parent := ListBox1;
end;

procedure TForm1.ListBox1DragOver(Sender: TObject; const Data: TDragObject;
  const Point: TPointF; var Operation: TDragOperation);
begin
  Operation := TDragOperation.Copy;
end;

end.
Ссылка на комментарий
  • 0

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

Имея отличное представление как должен работать механизм Drag&Drop, я столкнулся со следующим - OnDragDrop вообще не хочет работать (т.е. он тупо вообще не вызывается).

Поэтому я решил свой вопрос примерно так:

 

Оба списка TListBox должны иметь свойство AllowDrag = True.

Если какой-либо TListBox расположен на панели или другом компоненте, то данный компонент должен иметь свойство HitTest = True.

Это "предисловие" (иначе механизм не будет работать вообще).

 

В TListBox, который "приемник":

procedure TfmMain.ListBox2DragOver(Sender: TObject; const Data: TDragObject; const Point: TPointF;
  var Operation: TDragOperation);
begin
  Operation := TDragOperation.Move;
  if Data.Source is TListboxItem then
    TListbox(Sender).AddObject(TListboxItem(Data.Source));
end;

В данном случае выбранный TListBoxItem переместится в TListBox2.

 

P.S. Однако, я еще не разобрался с Drag&Drop при условии работы на планшете под управлением Windows.

Ссылка на комментарий
  • 0

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

Если Вы будете делать "копию" (TDragOperation.Copy), то учтите - DragOver у Вас будет вызываться постоянно, пока курсор с перемещаемым элементом находится над списком TListBox2. И, соответственно, вызов будет постоянно туда копировать все новые и новые элементы. Так-что надо придумать "проверку" внутри ListBox2DragOver.

 

Вот такие вот "свистоперделки" ))

А пока, параллельно, до конца пытюсь понять - как именно в FMX работает Drag&Drop.

И наши уважаемые гуру меня не убедят в том, что он работает правильно )) Так как понятие "правильно" в данном случае зависит от обстоятельств (точнее - от множества факторов))

Ссылка на комментарий
  • 0

Тоже это обошел, но несколько подругому - использовал обработчики procedure DragOver и DragDrop формы, соответственно смотря попадаю ли на нужный компонент и пересчитывая координаты.

Ссылка на комментарий
  • 0

Тоже это обошел, но несколько подругому - использовал обработчики procedure DragOver и DragDrop формы, соответственно смотря попадаю ли на нужный компонент и пересчитывая координаты.

Я об этом думал. Но у меня ситуация немного сложнее с пересчетом координат) (это я снова про "свистоперделки")))

Ссылка на комментарий
  • 0

Спасибо, Ярослав!

"Будет. XE7"

Приятно конечно. Жаль только то что "будет", а не есть. При условии того, что она уже исправлена (как Вы говорите), было бы еще лучше - если бы эти исправления были применимы и к текущей версии.

Представьте себе ситуацию, когда делаешь софт, обходишь ошибки FMX, чего только не придумываешь... И даже добиваешься, ценой огромных усилий и потерянного времени, нужного результата, а тут выходит новая версия XE! И выход новой версии не всегда упрощает поставленные задачи. Так как при большей "совместимости" можно легко перенести проект на новую XE. А в нашем случае получается, что переход занимает приличное время...

Я думаю Вы меня понимаете.

 

P.S. Встречный вопрос - когда она будет?

Изменено пользователем AlexG
Ссылка на комментарий
  • 0
  • Администраторы

Я вас понимаю, но ваше пожелание, к сожалению, направлено не по адресу. Я разработчик, а не менеджер. Так что лишь констатирую факт, что проблема исправлена...

Ссылка на комментарий
  • 0

Я не к тому)

 

Я прекрасно понимаю, что это не в Ваших силах. Просто высказал свое мнение, что накопившиеся "исправления" Embarcadero не использует для текущих версий, а только в новых...

 

Кроме того - было бы очень интересно узнать - что нового будет в XE7? Где можно подробнее узнать уже сейчас - какие новые механизмы, оптимизация и т.д.?

 

С Уважением, Алексей!

Ссылка на комментарий
  • 0
  • Администраторы
  1. Я думаю, что пока предварительная информация доступна в виде тем тут: http://delphitour.ru/ Ждать осталось не долго, так что уже в скором времени будет доступна полная информация об этом.
  2. Еще у Embarcadero есть программа закрытого бета-тестирования, на которой даются ранний доступ к новым версиям среды. Я думаю, что для вас это будет актуально в будущем. В этом случае вы будите в полном курсе, какая работа идет и что новое появляется между каждыми версиями беты.
Ссылка на комментарий
  • 0

Тоже это обошел, но несколько подругому - использовал обработчики procedure DragOver и DragDrop формы, соответственно смотря попадаю ли на нужный компонент и пересчитывая координаты.

Извиняюсь на некропостинг, но как вы это сделали? У моих форм нет DnD событий =/

Ссылка на комментарий
  • 0
private
....
    procedure DragOver(const Data: TDragObject; const Point: TPointF; var Operation: TDragOperation); override;
    procedure DragDrop(const Data: TDragObject; const Point: TPointF); override;
....

procedure TMainForm.DragOver(const Data: TDragObject; const Point: TPointF; var Operation: TDragOperation);
begin
  inherited;
  Operation:=TDragOperation.Link;
end;

procedure TMainForm.DragDrop(const Data: TDragObject; const Point: TPointF);
begin
... свой код...
  inherited;
end;
Ссылка на комментарий
  • 0

Господа!

Благодаря г-ну Vovanse теперь можем перетаскивать файлы в свою программу.

А кто-нибудь пытался осуществить обратную операцию?

Имеется в виду случай, когда программа на FireMonkey является источником D'n'D данных о перетаскиваемых файлах.

В VLC это решается через IDropSource (http://www.webdelphi.ru/2012/01/zametki-pro-dragdrop-v-delphi/), а как быть в FireMonkey при MacOS?

Не могу найти инфу.  :(  Может существует какой-нибудь компонент для этого? Помогите советом, плз!

Ссылка на комментарий
  • 0
  • Администраторы

Просьба для новых вопросов, создавать отдельную тему, а не устраивать помойку из одной тем. Спасибо. Тема на этом закрыта. 

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...