by特にQGraphicsView周りのD&Dイベント処理がややこしかったので覚書。Qt4.7.2,Windows7Homeで確認。その他の環境は未確認。acceptする,しないはevent->accept()をコールする,しないの意味。実装方法は,各クラスを継承した自作クラスで(一つのクラスのみで)D&Dを実装する方法。筆者は残念なプログラマなので信憑性もそれに順ずる。QWidget:acceptDrops既定値はfalse。acceptDropsをtrueにしないとハンドラが呼ばれない。TopLevelWidgetかつ子WidgetにacceptDropsがtrueのWidgetを持つ場合はWindow表示時に自動でsetAcceptDrops(true)される。dragEnterEventでacceptしないとその他のハンドラが呼ばれない。dragMoveEventは処理しなくても良い。実装方法:dragEnterEventでaccept,dropEventでdrop時の処理を実装して,acceptDropsをtrueにする。QGraphicsView:acceptDrops既定値はtrue。acceptDropsをfalseにすればハンドラは呼ばれない。Sceneがセットされていない時はQWidgetと同じ。Sceneがセットされると以下の動作をする。dragEnterEventでacceptしなくてもdragMoveEventは呼ばれる。各ハンドラではイベントをScene用にマッピングしてSceneに渡す。dragMoveEventではSceneの処理結果でacceptを上書き(setAccept)する。結果,dragEnterEventでacceptしてもdragMoveEventで上書きされてしまう。実装方法1(ViewのみでD&Dを受付け,Sceneにイベントを渡さない):dragEnterEvent,dragMoveEvent,dragLeaveEvent,dropEventを,基底クラスの関数を呼ばないように上書きする。あとはQWidgetと同じ。実装方法2(Viewの全域でD&Dを受け付けるがSceneにもイベントを渡す):dragMoveEventで基底クラスの関数を呼んだ後にacceptする。dropEventではdrop時の処理を実装し,基底クラスの関数を呼ぶ。QGraphicsScene各ハンドラはViewを経由して呼び出される。Sceneにポジションマッピング済みのイベントを受け取るので,Scene上の位置が必要ならこちらが便利。dragMoveEventではItemのacceptDropsがtrueの場合のみItemのdragEnterEvent,dragMoveEvent,dragLeaveEventを呼び出す。有効なItemが無ければeventはisAcceptedはfalseかつIgnoreActionをセットされる。実装方法1(SceneのみでD&Dを受付け,Itemにイベントを渡さない):dragMoveEventでacceptし,基底クラスの関数を呼び出さない。dropEventではdrop時の処理を実装する(基底クラスの関数は呼んでもItemにイベントは渡らない)。実装方法2(Scene全域でD&Dを受付けるがItemにもイベントを渡す):dragMoveEventで基底クラスの関数を呼んだ後にevent->accept()とevent->setDropAction(Qt::DropAction)を呼ぶ。DropActionはCopyActionなら+付き,LinkActionなら矢印付き,MoveActionなら何もつかない四角形のアイコン(マウスカーソル)になる(Windows7の場合)。Item上ではItem固有のアイコンにする場合は,dropActionがIgnoreActionの場合のみsetDropActionする。QGraphicsItemacceptDrops既定値はfalse。acceptDropsをtrueにしておくと,dragEnterEvent又はdragMoveEventでevent->ignoreしない限りdropEventは呼ばれる。実装方法:dropEventにdrop時の処理を実装して,acceptDropsをtrueにする。その他:QGraphicsViewやQTextEditなど,acceptDropsの既定値がtrueのWidgetを置くと親WidgetでD&Dイベントを受け取れなくなる。親WidgetでD&Dイベントを処理するならこれらのWidgetにsetAcceptDrops(false)するか,必要に応じてevent->ignore()するように再定義した派生クラスに変える必要がある。by動作確認しつつちょっと修正。調べれば調べる程ヤヤコシイ。byQWidgetで動作確認できるサンプル書いてみました。コード行が少なくなるように書いてるので,コーディングマナーはアレですが。d_d_widget.cppだけで動くはず。QLabel(".cppファイルを受付けます。Dropだけで1カテゴリできちゃいそうですなぁ。