Solved Simulating an editable QLabel: cannot clean-up redundant widget.
-
In the application I'm developing it is sometimes desired that the user can modify the text in a QLabel.
The problem of how to do this has been posed several times, but I have seen only suggestions to an answer, not working code. The following approach has been suggested:- create a QLineEdit widget and display it instead of the QLabel..
- The user enters a new text in the QLineEdit widget.
- when done (on Return), the new text is copied from the QLineEdit to the QLabel widget.
- The QLineEdit widget can be eliminated, the QLabel is made visible again.
I have implemented the scheme above, and it works, but the implementation is not 'clean' in that I cannot delete the auxiliary QLineWidget after it has been used. When I delete lineEdit, memory is corrupted. How should I do this instead?
I have trimmed my code to get a minimal example showing the issue. All, I think, is contained in the slot function MyWidget::mousePressEvent(), given below. MyWidget is a Q_OBJECT demo-class, directly derived from QWidget, with only one data member: QLabel* _qlabel;
On a mouse-click, a new QLineEdit instance lineEdit is allocated and initialised with the text of the QLabel. In the layout, the new QLineEdit is swapped with the QLabel. Next, a lambda-expression is defined that is used as a slot when the user presses Return.
The lambda expression copies the text back from QLineEdit to the QLabel, and it swaps the widgets again.Her is my problem: if I just delete the auxiliary QLineEdit widget, as it is no longer needed, the memory is corrupted (as valgrind clearly shows). If I only hide the lineEdit, memory stays good, everything looks ok, but the memory allocated to lineEdit will only be cleared when the whole widget goes (as QLabel* _qlabel is the parent). Even worse, when I don't set qlable as the parent (i.e. no parent), I still cannot delete lineEdit. This would leave me with a memory leak.
How should I handle such a case? I would like to delete the intermediary lineEdit entirely, leaving no traces that the qlabel text has been edited.void MyWidget::mousePressEvent( QMouseEvent* ) { // Create a lineEdit, initialize with qlabel's text auto lineEdit = new QLineEdit( _qlabel ); lineEdit->setText( _qlabel->text() ); lineEdit->setFocus(); // exchange widgets in layout; delete old layout item. delete layout()->replaceWidget( _qlabel, lineEdit ); // lambda for refreshing the label. auto doUpdate = [this,lineEdit]() { delete layout()->replaceWidget( lineEdit, _qlabel ); _qlabel->setText( lineEdit->text() ); #if 0 lineEdit->hide(); // works, but memory not timely cleaned. #else disconnect( lineEdit ); lineEdit->setParent(nullptr); delete lineEdit; // crash, or at least memory corruption! #endif }; connect( lineEdit, &QLineEdit::returnPressed, doUpdate ); }
-
Hi,
You are over-engineering it. Create the QLineEdit once and just show/hide it as required. There's no reason to delete and re-create it all the time.
-
Thanks for responding. But this was precisely my question! Throwing away an object that is no longer needed is not bad engineering, I would say. But throwing it away somehow screws-up the qt-internals,
even when I explicitly disconnect and set the parent to nil. I don't understand. I fear the connect(lineEdit,....) statement somehow puts lineEdit in Qt-s belly where it cannot be undone easily.Furthermore, I made the QLabel instance the parent of the QLineEdit so that Qt take care of deallocation. Instead, I could also create the QLineEdit without setting its parent. In that case I would have a memory leak if I don't delete the object myself. But the memory corruption is still present.
Below I post a typical output of valgrind after changing the text and pressing the return key,
==9178== Memcheck, a memory error detector ==9178== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==9178== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==9178== Command: ./Linux-5.3/bin/editablelabel ==9178== ==9178== Invalid read of size 8 ==9178== at 0x7E60404: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D05834: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA9DA: QLineEdit::keyPressEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C07C86: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD1126: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C213CC: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7402D31: QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== by 0x73DE33B: QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== Address 0x18a11418 is 8 bytes inside a block of size 248 free'd ==9178== at 0x4C2FBEB: operator delete(void*, unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x7E5470D: QObjectPrivate::deleteChildren() (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C02FF5: QWidget::~QWidget() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA7E8: QLineEdit::~QLineEdit() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x4037D8: MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}::operator()() const (MyWidget.cpp:38) ==9178== by 0x403BB3: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}>::call({lambda()#1}&, void**) (qobjectdefs_impl.h:146) ==9178== by 0x403B94: void QtPrivate::Functor<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0>::call<QtPrivate::List<>, void>({lambda()#1}&, void*, {lambda()#1}&*) (qobjectdefs_impl.h:256) ==9178== by 0x403B63: QtPrivate::QFunctorSlotObject<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:443) ==9178== by 0x7E608B2: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7E608E4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D0582C: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA9DA: QLineEdit::keyPressEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== Block was alloc'd at ==9178== at 0x4C2E94F: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x6CF840F: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFC130: QLineEdit::QLineEdit(QWidget*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x403830: MyWidget::mousePressEvent(QMouseEvent*) (MyWidget.cpp:19) ==9178== by 0x6C06E1D: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD0D75: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6BCFE42: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C1E286: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C2135D: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== ==9178== Invalid read of size 1 ==9178== at 0x7E6040C: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D05834: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA9DA: QLineEdit::keyPressEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C07C86: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD1126: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C213CC: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7402D31: QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== by 0x73DE33B: QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== Address 0x147cb380 is 32 bytes inside a block of size 88 free'd ==9178== at 0x4C2FBEB: operator delete(void*, unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x6D071D4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E5470D: QObjectPrivate::deleteChildren() (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C02FF5: QWidget::~QWidget() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA7E8: QLineEdit::~QLineEdit() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x4037D8: MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}::operator()() const (MyWidget.cpp:38) ==9178== by 0x403BB3: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}>::call({lambda()#1}&, void**) (qobjectdefs_impl.h:146) ==9178== by 0x403B94: void QtPrivate::Functor<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0>::call<QtPrivate::List<>, void>({lambda()#1}&, void*, {lambda()#1}&*) (qobjectdefs_impl.h:256) ==9178== by 0x403B63: QtPrivate::QFunctorSlotObject<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:443) ==9178== by 0x7E608B2: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7E608E4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D0582C: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== Block was alloc'd at ==9178== at 0x4C2E94F: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x7E5F174: QObject::QObject(QObject*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7583182: QInputControl::QInputControl(QInputControl::Type, QObject*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== by 0x6CF841E: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFC130: QLineEdit::QLineEdit(QWidget*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x403830: MyWidget::mousePressEvent(QMouseEvent*) (MyWidget.cpp:19) ==9178== by 0x6C06E1D: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD0D75: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6BCFE42: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C1E286: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== ==9178== Invalid read of size 8 ==9178== at 0x7E60416: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D05834: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA9DA: QLineEdit::keyPressEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C07C86: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD1126: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C213CC: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7402D31: QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== by 0x73DE33B: QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== Address 0x147cb3a8 is 72 bytes inside a block of size 88 free'd ==9178== at 0x4C2FBEB: operator delete(void*, unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x6D071D4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E5470D: QObjectPrivate::deleteChildren() (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C02FF5: QWidget::~QWidget() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA7E8: QLineEdit::~QLineEdit() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x4037D8: MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}::operator()() const (MyWidget.cpp:38) ==9178== by 0x403BB3: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}>::call({lambda()#1}&, void**) (qobjectdefs_impl.h:146) ==9178== by 0x403B94: void QtPrivate::Functor<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0>::call<QtPrivate::List<>, void>({lambda()#1}&, void*, {lambda()#1}&*) (qobjectdefs_impl.h:256) ==9178== by 0x403B63: QtPrivate::QFunctorSlotObject<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:443) ==9178== by 0x7E608B2: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7E608E4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D0582C: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== Block was alloc'd at ==9178== at 0x4C2E94F: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x7E5F174: QObject::QObject(QObject*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7583182: QInputControl::QInputControl(QInputControl::Type, QObject*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== by 0x6CF841E: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFC130: QLineEdit::QLineEdit(QWidget*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x403830: MyWidget::mousePressEvent(QMouseEvent*) (MyWidget.cpp:19) ==9178== by 0x6C06E1D: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD0D75: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6BCFE42: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C1E286: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== ==9178== Invalid read of size 8 ==9178== at 0x7E53B70: QObjectPrivate::maybeSignalConnected(unsigned int) const (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7E60485: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D05834: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA9DA: QLineEdit::keyPressEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C07C86: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD1126: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C213CC: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7402D31: QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== Address 0x147cb3a0 is 64 bytes inside a block of size 88 free'd ==9178== at 0x4C2FBEB: operator delete(void*, unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x6D071D4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E5470D: QObjectPrivate::deleteChildren() (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6C02FF5: QWidget::~QWidget() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFA7E8: QLineEdit::~QLineEdit() (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x4037D8: MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}::operator()() const (MyWidget.cpp:38) ==9178== by 0x403BB3: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}>::call({lambda()#1}&, void**) (qobjectdefs_impl.h:146) ==9178== by 0x403B94: void QtPrivate::Functor<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0>::call<QtPrivate::List<>, void>({lambda()#1}&, void*, {lambda()#1}&*) (qobjectdefs_impl.h:256) ==9178== by 0x403B63: QtPrivate::QFunctorSlotObject<MyWidget::mousePressEvent(QMouseEvent*)::{lambda()#1}, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:443) ==9178== by 0x7E608B2: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7E608E4: ??? (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6D0582C: QWidgetLineControl::processKeyEvent(QKeyEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== Block was alloc'd at ==9178== at 0x4C2E94F: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==9178== by 0x7E5F174: QObject::QObject(QObject*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x7583182: QInputControl::QInputControl(QInputControl::Type, QObject*) (in /usr/local/qt-5.15.2/lib/libQt5Gui.so.5.15.2) ==9178== by 0x6CF841E: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6CFC130: QLineEdit::QLineEdit(QWidget*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x403830: MyWidget::mousePressEvent(QMouseEvent*) (MyWidget.cpp:19) ==9178== by 0x6C06E1D: QWidget::event(QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BCA5BE: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6BD0D75: QApplication::notify(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x7E2C3E9: QCoreApplication::notifyInternal2(QObject*, QEvent*) (in /usr/local/qt-5.15.2/lib/libQt5Core.so.5.15.2) ==9178== by 0x6BCFE42: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178== by 0x6C1E286: ??? (in /usr/local/qt-5.15.2/lib/libQt5Widgets.so.5.15.2) ==9178==
-
Please provide a minimal, compilable example so we can reproduce your issue. Deleting a widget will not crash Qt - you must be doing something wrong. For instance you must not delete a widget inside a slot which is called due to a signal of this widget but use deleteLater() as you do in your example.
/moved to General Qt since it's a general Qt usage question.
-
Hi
Just as a note:
You can have an editable Qlabelui->label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable); QTextDocument *td = ui->label->findChild<QTextDocument *>(); if (td) { connect( td, &QTextDocument::contentsChanged, this, [td]() { qDebug() << td->toRawText(); }); }
-
@mrjj Thanks! I was not aware of this possibility. Maybe I should follow this route.
I will still post my original code, as suggested earlier, as something must be wrong there, and I don't see the culprit
(meaning I still don't fully understand Qt)..
. -
Here is a small example.
In succession I post a header file and two .cpp files + qmake .pro.header file: MyWidget.h:
#include <QtWidgets/QWidget> #include <QtWidgets/QLabel> class MyWidget : public QWidget { Q_OBJECT private: QLabel* _qlabel; public: MyWidget(); protected: void mousePressEvent(QMouseEvent*) override; };
Implementation file MyWidget.cpp:
#include "MyWidget.h" #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QLineEdit> MyWidget::MyWidget() { _qlabel = new QLabel( "Click to edit text."); QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget( _qlabel ); show(); } void MyWidget::mousePressEvent( QMouseEvent* ) { // Create a lineEdit, initialize with qlabel's text auto lineEdit = new QLineEdit( _qlabel ); lineEdit->setText( _qlabel->text() ); lineEdit->setFocus(); // exchange widgets in layout; delete old layout item. delete layout()->replaceWidget( _qlabel, lineEdit ); // lambda for refreshing the label. auto doUpdate = [this,lineEdit]() { delete layout()->replaceWidget( lineEdit, _qlabel ); _qlabel->setText( lineEdit->text() ); #if 0 lineEdit->hide(); // works, but memory leaked or not timely cleaned. #else disconnect( lineEdit ); lineEdit->setParent(nullptr); delete lineEdit; // crash, or at least memory corruption! #endif }; connect( lineEdit, &QLineEdit::returnPressed, doUpdate ); }
main.cpp:
#include "MyWidget.h" #include <QtWidgets/QApplication> int main(int argc, char *argv[]) { QApplication app( argc, argv ); auto widget = std::unique_ptr<MyWidget>(new MyWidget); return app.exec(); }
and finally a qmake .pro file: qmake -o Makefile MyWidget.pro
TEMPLATE = app QT += widgets CONFIG += qt SOURCES += MyWidget.cpp main.cpp HEADERS += MyWidget.h TARGET = MyWidget
-
Hi
did you trydelete lineEdit;
to
lineEdit-deleteLater();
-
@BwvB You created an example but did not read my post:
For instance you must not delete a widget inside a slot which is called due to a signal of this widget but use deleteLater() as you do in your example.
-
@Christian-Ehrlicher
Christian, you were quit right. In my eagerness to post a minimal example, I forgot to follow-up on your suggestion...Indeed, changing
delete lineEdit
into
lineEdit->deleteLater()
resolved the issue. valgrind is happy and so am I.
Thanks for your help!Regards,
Bertwim