Important: Please read the Qt Code of Conduct -

Dragging a tab from QTabWidget into a separate window

  • Hey there,

    My web browser project has a QTabWidget that works fine, but I am interested in extending its abilities. I would like to be able to drag a tab off the tab row and have it turn into its own window. Is this possible with Qt? All the major browsers like Chrome, Firefox, etc. do it.

  • Should be possible. Depending on whether you want it to be nicely animated or not, it might even be very simple. Define a minimum drag distance that a tab has to be moved outside of the QTabWidget before it is removed from that tab widget and inserted into another one that comes along with its own window.

    Would need to reimplement maybe mousePressEvent(), dragLeaveEvent() and/or dragMoveEvent(). With this you should be able to make a tab leave. Then either reimplement a dropEvent() for the window that is going to receive the tab, or just make the ripped out tab start its own window and everything.

  • Thanks! How would I set the minimum distance it needs to be pulled outside the QTabWidget? The tabs are currently set to be movable so I can rearrange the order of them. Will it interfere with that feature?

  • You should be able to just add it on top.

    Subclass QTabWidget, add a new property for your minimum "rip off distance" (int) and one for the "initial click position" (QPoint), then reimplement the mousePressEvent so that you record the position of the click (that's all for that function), reimplement mouseReleaseEvent and reset the "initial click position" in there.

    Finally reimplement dragMoveEvent().There you measure the distance between the "initial click position" and the current position. You probably want to restrict that measurement to the y-coordinate of the two QPoints you now have (initial and current), so that the user can only "rip off" a tab when moving it perpendicular to the orientation of the QTabWidgets tab bar. That way it won't interfere with the normal tab movement.
    So in the dragMoveEvent() you have something like:
    //QPoint initialMouseClick is what you recorded in mousePressEvent
    //int ripOffDistance; could be set to maybe 30 pixels?
    if(initialMouseClick.isValid() && qabs((initialMouseClick - event.pos()).y()) >= ripOffDistance)
    //take the tab, put it in a new window

    There are some finer details I didn't mention (e.g. when you reset initialMouseClick, make it invalid via initialMouseClick = QPoint(), don't set it to zero), but I hope this is enough for you to get the job done. I sadly don't have the time right now to be absolutely precise.

    PS: Maybe take a look at the "drag&drop examples": .

  • Yeah thats a great start, thanks for your help! How do I tell it to only rip off the tab that the cursor is on rather than the whole QTabBar?

  • How about a look into the "documentation": ?

    @ QWidget *rippedOffTab = this->currentWidget();
    //do with rippedOffTab whatever you want@

Log in to reply