App crashing on dropevent in QtabWidget
-
I am trying to drag tab from one QtabWidget to another QtabWidget i have implemented my code based on this python solution " https://forum.qt.io/topic/67542/drag-tabs-between-qtabwidgets/5 " everything is working as expected but my app is crashing when i drop my tab in QtabWidget, my app is crashing exactly inside dropEvent(QDropEvent) addTab() and insertTab() i have no idea what is causing this any help is appreciated.
class CustomTab : public QTabWidget { public: CustomTab(); protected: void mouseMoveEvent(QMouseEvent *e) override; void dragEnterEvent(QDragEnterEvent *e) override; void dragLeaveEvent(QDragLeaveEvent *e) override; void dropEvent(QDropEvent *e) override; };
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QSplitter *splitter = new QSplitter; CustomTab *tab1 = new CustomTab; CustomTab *tab2 = new CustomTab; tab1->addTab(new QWidget(), "TAB ONE 1"); tab1->addTab(new QWidget(), "TAB ONE 2"); tab2->addTab(new QWidget(), "TAB TWO 1"); tab2->addTab(new QWidget(), "TAB TWO 2"); splitter->addWidget(tab1); splitter->addWidget(tab2); QGridLayout *gL = new QGridLayout; gL->addWidget(splitter); ui->centralwidget->setLayout(gL); } MainWindow::~MainWindow() { delete ui; } // Custom Tab CustomTab::CustomTab() { setAcceptDrops(true); setMovable(true); setMouseTracking(true); setTabsClosable(true); tabBar()->setMouseTracking(true); } void CustomTab::mouseMoveEvent(QMouseEvent *e) { if (e->buttons() != Qt::RightButton) return; QPoint global_pos = mapToGlobal(e->pos()); QTabBar *tabbar = tabBar(); QPoint posInTab = tabbar->mapFromGlobal(global_pos); int indexTab = tabbar->tabAt(e->pos()); QRect tabrect = tabbar->tabRect(indexTab); QPixmap pix = QPixmap(tabrect.size()); tabbar->render(&pix, QPoint(), QRegion(tabrect)); QMimeData mimedata = QMimeData(); QDrag drag = QDrag(tabbar); drag.setMimeData(&mimedata); drag.setPixmap(pix); QCursor cursor = QCursor(Qt::OpenHandCursor); drag.setHotSpot(e->pos() - posInTab); drag.setDragCursor(cursor.pixmap(), Qt::MoveAction); drag.exec(Qt::MoveAction); } void CustomTab::dragEnterEvent(QDragEnterEvent *e) { e->accept(); if (e->source()->parent() != this) return; } void CustomTab::dragLeaveEvent(QDragLeaveEvent *e) { e->accept(); } void CustomTab::dropEvent(QDropEvent *e) { if (e->source()->parent() == this) return; e->setDropAction(Qt::MoveAction); e->accept(); int counter = count(); QTabWidget *parentWidget = qobject_cast<QTabWidget *>(e->source()->parent()); // crashing from here : if (counter == 0) { addTab(parentWidget->currentWidget(), parentWidget->tabText(parentWidget->currentIndex())); } else { insertTab(counter + 1, parentWidget->currentWidget(), parentWidget->tabText(parentWidget->currentIndex())); } }
-
Hi,
I made an example based on the code you provided and ran it through a debugger, it crashed in
qdrag.cpp
, when it tried to delete yourQDrag
data after leavingmouseMoveEvent
scope.I allocated
QMimeData
on the heap and it worked, I was able to drag and drop tabs.in
mouseMoveEvent
:
QMimeData *mimedata = new QMimeData();
See if this is it.
-
@Narutoblaze said in App crashing on dropevent in QtabWidget:
// crashing from here :
Then you should look at the debugger to see what's wrong there. I would guess parentWidget is a nullptr.
-
@Narutoblaze said in App crashing on dropevent in QtabWidget:
QTabWidget *parentWidget = qobject_cast<QTabWidget *>(e->source()->parent());
parentWidget == null ?
-
@Christian-Ehrlicher @mpergand I have debugged this portion of the code and found it is not null.
qDebug() << parentWidget(); qDebug() << parentWidget()->tabText(parentWidget()->currentIndex());
I got the address of parentWidget & the text of the parentWidget "values received provided below"
output :
0xc00009e230 TAB ONE 1
-
Hi,
I made an example based on the code you provided and ran it through a debugger, it crashed in
qdrag.cpp
, when it tried to delete yourQDrag
data after leavingmouseMoveEvent
scope.I allocated
QMimeData
on the heap and it worked, I was able to drag and drop tabs.in
mouseMoveEvent
:
QMimeData *mimedata = new QMimeData();
See if this is it.
-
@Narutoblaze said in App crashing on dropevent in QtabWidget:
drag.setMimeData(&mimedata);
void QDrag::setMimeData(QMimeData *data) states:
Ownership of the data is transferred to the
QDrag
object.Whenever you read about a function taking "ownership" of a pointer that means Qt infrastructure will delete the object you passed when the now-parent object later gets destroyed. That can only be performed against an object allocated on the heap (
new
) not on the stack (local variable whose address you take with&
, like your code).Consequently @Abderrahmene_Rayene's code will address this correctly by creating your
QMimeData
object on the heap. Do not delete it yourself once you have passed tosetMimeData()
! -
@Narutoblaze Please read again what @JonB wrote. Especially what he copied from Qt documentation...
-
-