Important: Please read the Qt Code of Conduct -

How to get a pointer to a widget at current mouse position?

  • Hello to everyone.
    I need to get a pointer to a widget at current mouse cursor position. I know about widgetAt(); method, but it's not very suitable for me, because of following. I am developing draggable tabs like in Chrome or in Visual Studio, so I want the window to become a tab, when you drag it inside a QTabBar in another window. I have reimplemented mouseMoveEvent, and now I can move window by dragging my QTabBar. How can i find out, that mouse cursor is dragging tab and is over the QTabBar in another window? widgetAt(); is very good, but it will always return a pointer to the tab which I drag(becouse it is top-level widget). Is it possible to make some widget "invisible" for the widgetAt() method, but leave the widget visible for user?

  • Lifetime Qt Champion

    Im wondering if the normal drag events would be more helpful.
    If you dont want to subclass, you can use eventFilter.

  • @mrjj How can I use drag and drop for usual windows or widgets? I want to drag my tab as usual window (as if I dragged window title area). And how can I recieve the dragEnter event in this case?
    eventFilter is unsuitable, because I need to know to which object I should send the event.

  • Lifetime Qt Champion

    Subclass is the only way then. (if u cant use event filter)
    You can drag most things as a custom format.
    But not sure a window will trigger it if drag by caption as that is NOT a real drag.
    However, you might be able to make it work with startdrag.

  • @mrjj >But not sure a window will trigger it if drag by caption as that is NOT a real drag.
    That's okay. I can reimplement mouseMoveEvent of some widget and drag window by dragging the QTabBar widget(as you can see while dragging tabs in Chrome).
    What should I do to make DragEnterEvents, dropEvents, etc. triggered? How to start 'real' drag and recieve the dragEvents? I have tried to reimplement the dragEnterEvent, but it activates only if I drag some text/file inside it, but if I drag window it doesn't trigger.

  • Lifetime Qt Champion

    problem is that dragging by caption triggers nchittest native event.
    So not sure how to do it with an actual window as we need to call startdrag as we would for a widget or
    any place from the client area of the window.
    this following code is for dragging an item from list to area. (using a user image)
    so you could render the window as smaller? version and use that for drop icon but
    it comes back to how to detect the caption drag.

    I have no good idea for that if to be crossplatform. maybe others have better/some ideas.

    void PiecesList::startDrag(Qt::DropActions /*supportedActions*/) {
      QListWidgetItem* item = currentItem();
      QByteArray itemData;
      QDataStream dataStream(&itemData, QIODevice::WriteOnly);
      QPixmap pixmap = qvariant_cast<QPixmap>(item->data(Qt::UserRole));
      QPoint location = item->data(Qt::UserRole + 1).toPoint();
      QString test;
      dataStream << pixmap << location << test;
      QMimeData* mimeData = new QMimeData;
      mimeData->setData("image/x-puzzle-piece", itemData);
      QDrag* drag = new QDrag(this);
      drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2));
      if (drag->exec(Qt::MoveAction) == Qt::CopyAction)
        delete takeItem(row(item));

    Code mostly from
    ps. Test code. sloppy..:)

  • @mrjj okay, let's imagine that we solved problem with caption drag detection.
    My problem is that i don't want to render small image of my tab, I'd like to drag real tab as real window. I saw many examples, where dragging labels/pictures is shown, and where data is converted into bytearray. But I drag widget, which contains another child widgets, such as textareas with text inside and other, so i can't convert them into bytearray... That's why I thought that Drag&Drop isn't good way for me.

    I want to implement algorythm nearly like this:

    1. If user dragged tab outside QTabBar -> tab became a window and follow the mouse cursor.
    2. If count of tabs in current TabBar is 1, when user drag tab he just moves the window, no new windows created.
    3. If user dragged one tab (window) to some TabBar -> window becomes tab. //That's the main problem.
      Initially, everything was perfect, i implemented the first two steps, just by using mouseMoveEvents & it's globalPos() method, without using D&D. But the third step is my problem for many days...

  • Lifetime Qt Champion

    I can only think of bytearray with widget pointers and
    drop target would re-parent them and close window.
    But again, i dont know how to catch title dragging to start a drag.

    I would check with event filter on the test drop target to see if any info is even sent
    to the drop target if u drag a window over it.

  • @mrjj Reparenting is not a problem too. Problem is how to know, that the mouse cursor is inside QTabBar, during dragging the tab (window). If we will know it, we can do everything we want.

  • Lifetime Qt Champion

    what about finding widgetAt and reuse source and make it able to ignore a widget ?

  • @mrjj
    That's a great idea, but how can we make the widgetAt() able to ignore some widget? I thought about it earlier, but I don't know how to ignore a widget.

  • Lifetime Qt Champion

    We need to find the source code and see how it works before we can see
    if possible to alter it for ignore a widget.

  • @mrjj Hello.
    I have found source code of the widgetAt() method, but, as i understood, It's based on the loop and is hard to modify.
    So I decided to send some signal, while moving the window, to all avaible QTabBars and they will send a reply signal if their rect() contains current mouse position. That's the only way, that i see.

  • Lifetime Qt Champion

    Sounds ok to me. another signal based version of widgetAt :)

Log in to reply