ListViewのdelegateプロパティに指定したレイアウト情報にMouseAreaを配置した場合の謎動作について。
マウスカーソルがエリア外に出た時に発生するシグナルの「onExited」と押してたマウスが離された時に発生する「onReleased」が発生しない時があるのです。
実際に下のサンプルを動かすとわかるのですが。
普通にRectangleとかにMouseAreaを配置して以下の操作をします。
1.カーソルを四角の上に持ってく
2.マウスダウン(押しっぱなし)
3.カーソル移動して四角の外へ
4.マウスアップ(放す)
この時のログの流れはこんな感じ。
1.rect:onEntered
2.rect:onPressed
3.rect:onExited
4.rect:onReleased
操作の番号とイベント発生タイミングは一致してます。
なんとなく納得な流れ。
カーソルをウインドウの外まで持って行ってもマウスアップ時にonReleased発生します。
ListViewのdelegateに配置した場合のログの対応をとるとこんな感じ。
1.delegate:onEntered
2.delegate:onPressed
3.何も起きない
4.何も起きない
リストをうにょーーんと引っ張れるようになっているせいなのかなんなのか。
試しにサンプルでコメントして入れてありますが、ListViewの中に全体にMouseAreaをはっつけても同じでした。
当然その場合は、各delegateが直接シグナルを受け取れないのでいろいろ頑張る必要があります。
Qt Quick 1.1の機能で「preventStealing」を使うと意図した動作をするのですが、リストのスクロールがマウスのホイールのみになってドラッグできなくなります。
でしたが、「onCanceled」をひろうといいよと聞いたので試したところ。
1.delegate:onEntered
2.delegate:onPressed
3.delegate:onCanceled
4.何も起きない
となりました。
リリースはわからないもののListViewのマウスダウンした時のアイテムの外にでると「onCanceled」が発生するので期待する動きに近い感じになります。
サンプルの本体。
import QtQuick 1.0 Rectangle { id:_root width: 360 height: 360 // 比較に普通の四角 Rectangle{ id: _rectSample width: 100 height: 50 x: 10 y: 50 color: "#0000dd" // こっちにもマウスエリアを配置 MouseAreaLog{ tag: "rect:" } } // リストモデル ListModel{ id: _model // 2つくらいリストに登録 ListElement{ _message: "homuhomu" } ListElement{ _message: "hogehoge" } } // リスト用レイアウト Component{ id: _delegate Rectangle { width: _list.width height: _text.paintedHeight * 2 border.color: "#dddddd" border.width: 1 Text{ id: _text anchors.centerIn: parent text: _message } // これでリストの各項目でクリックイベントを拾う MouseAreaLog{ tag: "delegate:" + _message + ":" } } } // リスト ListView{ id: _list anchors.top: _rectSample.bottom anchors.left: _root.left anchors.right: _root.right anchors.bottom: _root.bottom clip: true model: _model delegate: _delegate // MouseAreaLog{ // anchors.fill: _list // tag: "listview:" // } } }
イベントログを出しやすくしたエレメント
// MouseAreaLog.qml import QtQuick 1.0 //import QtQuick 1.1 MouseArea { anchors.fill: parent hoverEnabled: true // preventStealing: true property string tag: "" // 追加 onCanceled: { console.debug(tag + "onCanceled"); } //クリック時にハイライトさせる onPressed: { console.debug(tag + "onPressed"); } onReleased: { console.debug(tag + "onReleased"); } //マウスオーバー onEntered: { console.debug(tag + "onEntered"); } onExited: { console.debug(tag + "onExited"); } // 長押し onPressAndHold: { console.debug(tag + "onPositionChanged"); } //クリック onClicked: { console.debug(tag + "onClicked"); } }
Masaya TAKAHASHI
今更なのかもしれませんが、おそらく
(ListViewの継承元である)Flickableのせいです。
interactiveがtrueのとき、
mousePressとmouseMoveとmouseReleaseのイベントを内部でacceptするよ、と書いてあります(/src/declarative/graphicsitems/qdeclarativeflickable.cpp)。
なのでそれより後にイベントハンドラは呼ばれません。
うにょーんと動かす処理でイベントを使っているということですかね。
なので、ListViewがうにょーんと動かないよう、interactive:falseで固定してやるとRectangleと同じになると思います。
あやね
> Masaya TAKAHASHI さん
情報ありがとうございます。
たしかに、interactive=falseにするとイベントが起きるのですが、うにょーんだけじゃなくて通常のスクロールもできなくなるっぽいので使える状況が限られる技かもしれませんね。