ListView: Long press and release to initiate a grab, move mouse to scroll, then click to release

  • Hello,

    I am trying to figure out how to change the way ListView responds to mouse events. I have a large, scrollable list, and I want to "long press" on the ListView widget to initiate scrolling. After the long press (and release), the list is "grabbed" and any movement of the mouse along the y-axis should result in scrolling of the List. A single click should release grabbed list.

    Is this possible?


  • I think that it is possible only by custom plugin with class inherited from listview (or maybe from flickable). Not sure, but I'll be at your place I will start from this point while solving this issue.

  • I think you should look at the Flickable scrollbar example( I can't find the link now but is somewhere in docs) . after the long press action you scroll your flickable element(I think it will work for listview) on y-axis based on your mouse position.

  • 2beers, hm, can't find how to track mouse without buttons pressed

  • Hmm, I thought I was being clever, but this doesn't work. When I try to set grabMouse() on the ListView, the program crashes. On the MouseArea, QGraphics complains there is no scene.

    @class MySystem : public QObject
    Q_INVOKABLE void grabMouse(QDeclarativeItem *item) { if(item) item->grabMouse(); }

    int main(void)
    view.rootContext()->setContextProperty("mysys", new MySystem());


    Item {
    ListModel { id: myModel; ListElement { type: "Dog"; age: 8 } ListElement { type: "Dog"; age: 8 } }
    Component { id: myDelegate; Text { text: type + ", " + age } }
    ListView {
    id: myList
    model: myModel
    delegate: myDelegate
    MouseArea {
    id: mymouse
    anchors.fill: parent
    onPressAndHold: {
    // This crashes:

                // This complains:  QGraphicsItem::grabMouse: cannot grab mouse without scene
                // mysys.grabMouse(mymouse);
                // This complains: QGraphicsItem::grabMouse: cannot grab mouse while invisible
                // mysys.grabMouse(listItem)


  • Thinking out loud here, I could create a MouseGrabArea class similar to MouseArea...

    No idea if something like this would work, but will try tomorrow:

    @ListView {
    id: mylist

    MouseGrabArea { height: parent.height; width: parent.width; }

    // Psuedo code...
    class MouseGrabArea : public QDeclarativeItem
    public slot:
    void onMousePress() { m_press_time = gettime(); } // Time in milliseconds
    void onMouseRelease() { if(gettime() - m_press_time > 800) { this.grabMouse(); } else { this.releaseMouse(); } }

  • Hi,

    Are you looking for standard "flicking" behavior after the long press, or just panning? If the latter, putting a MouseArea over the ListView, and using it to manually manipulate the ListView's position (using e.g. positionViewAtIndex, or contextX/Y) might work.


  • I solved this with a little help from C++. Using rootContext->setContextProperty(), I created a C++ class with Q_INVOKABLE methods that:

    @setGrabCursor(bool doit) const

    From my app, when I detect a long press on my ListView delegate, I call setGrabCursor(true) and make a full screen mousearea active that marks mouse events as accepted. I tie the mouse y coordinate to the listview contentY inside of a onPositionChanged() handler. On single click of the mousearea, I call setGrabCursor(false).

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.