[QT6][C++] Deleting item from Custom ListWidgetItem corrupting other entry in QT
-
I am working on application, In which QDialog will be populated with some Custom ListWidgetItem labeled from 1 to 5, now in application requirement is that some other thread will delete the Items from dialog.
Problem:
As soon as first Item is deleted, it will corrupt the next item. (I can see blank item in dialog)
Note : Using Custom ListWidgetItem is important to make it scalable later.
Code:
- mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QtWidgets/QDialog> #include <QtWidgets/QListWidget> #include <QLabel> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H //Custom WidgetItem class UploadJobListDialog : public QDialog { Q_OBJECT public: explicit UploadJobListDialog(std::vector<std::string> jobNames, QWidget* parent = NULL); void removeit(size_t i); private: void addListWidgetItems(); QListWidget* m_pListWidget = nullptr; std::vector<std::string> m_pJobNames = {}; }; class QCustomListWidgetItem : public QWidget { Q_OBJECT public: explicit QCustomListWidgetItem(std::string labelText, QWidget* parent = NULL); private: QLabel* m_pItemLabel = nullptr; std::string m_pJobName; };- main.cpp
#include "mainwindow.h" #include <QApplication> #include <QHBoxLayout> #include <thread> #include <unistd.h> #include <mutex> std::mutex a; QCustomListWidgetItem::QCustomListWidgetItem(std::string labelText, QWidget* parent) : QWidget(parent), m_pJobName(labelText) { m_pItemLabel = new QLabel(QString::fromStdString(m_pJobName), this); } UploadJobListDialog::UploadJobListDialog(std::vector<std::string> jobNames, QWidget* parent) : QDialog(parent) , m_pJobNames(jobNames) { addListWidgetItems(); } void UploadJobListDialog::addListWidgetItems() { m_pListWidget = new QListWidget(this); QString listStyle( "QListWidget::item:hover," "QListWidget::item:disabled:hover," "QListWidget::item:hover:!active," "{background:#FFFFFF;}"); m_pListWidget->setStyleSheet(listStyle); m_pListWidget->setFixedSize(QSize(470, 150)); for (const auto& jobName: m_pJobNames) { // std::shared_ptr<QListWidgetItem> listWidgetItem = std::make_shared<QListWidgetItem>(QString::fromStdString(jobName)); QListWidgetItem* listWidgetItem = new QListWidgetItem(m_pListWidget); QCustomListWidgetItem* customListWidget = new QCustomListWidgetItem(jobName, m_pListWidget); listWidgetItem->setSizeHint(customListWidget->size()); listWidgetItem->setFlags(listWidgetItem->flags() & ~Qt::ItemIsSelectable); m_pListWidget->addItem(listWidgetItem); m_pListWidget->setItemWidget(listWidgetItem, customListWidget); } } void UploadJobListDialog::removeit(size_t ui) { std::lock_guard<std::mutex> lock(a); for (int i = 0; i < m_pListWidget->count(); ++i) { sleep(10); QListWidgetItem* item = m_pListWidget->item(0); if (!item) continue; QCustomListWidgetItem* widget = dynamic_cast<QCustomListWidgetItem*>(m_pListWidget->itemWidget(item)); if (!widget) continue; int nRow = m_pListWidget->row(item); QListWidgetItem* pDeleteItem = m_pListWidget->takeItem(nRow); if (pDeleteItem != NULL) { delete pDeleteItem; } } } int main(int argc, char *argv[]) { QApplication a(argc, argv); std::vector<std::string> jobs = {"1","2","3","4","5"}; static UploadJobListDialog obj(jobs); std::thread([=] { obj.removeit(jobs.size()); } ).detach(); obj.exec(); return 0; }Questions:
- What is leading to corruption?
- Am I doing something wrong?
Ps: I am new to QT, any help is greatly appreciated.
-
You are creating 2 objects when you add an item, but you only delete one.
-
I am working on application, In which QDialog will be populated with some Custom ListWidgetItem labeled from 1 to 5, now in application requirement is that some other thread will delete the Items from dialog.
Problem:
As soon as first Item is deleted, it will corrupt the next item. (I can see blank item in dialog)
Note : Using Custom ListWidgetItem is important to make it scalable later.
Code:
- mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QtWidgets/QDialog> #include <QtWidgets/QListWidget> #include <QLabel> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H //Custom WidgetItem class UploadJobListDialog : public QDialog { Q_OBJECT public: explicit UploadJobListDialog(std::vector<std::string> jobNames, QWidget* parent = NULL); void removeit(size_t i); private: void addListWidgetItems(); QListWidget* m_pListWidget = nullptr; std::vector<std::string> m_pJobNames = {}; }; class QCustomListWidgetItem : public QWidget { Q_OBJECT public: explicit QCustomListWidgetItem(std::string labelText, QWidget* parent = NULL); private: QLabel* m_pItemLabel = nullptr; std::string m_pJobName; };- main.cpp
#include "mainwindow.h" #include <QApplication> #include <QHBoxLayout> #include <thread> #include <unistd.h> #include <mutex> std::mutex a; QCustomListWidgetItem::QCustomListWidgetItem(std::string labelText, QWidget* parent) : QWidget(parent), m_pJobName(labelText) { m_pItemLabel = new QLabel(QString::fromStdString(m_pJobName), this); } UploadJobListDialog::UploadJobListDialog(std::vector<std::string> jobNames, QWidget* parent) : QDialog(parent) , m_pJobNames(jobNames) { addListWidgetItems(); } void UploadJobListDialog::addListWidgetItems() { m_pListWidget = new QListWidget(this); QString listStyle( "QListWidget::item:hover," "QListWidget::item:disabled:hover," "QListWidget::item:hover:!active," "{background:#FFFFFF;}"); m_pListWidget->setStyleSheet(listStyle); m_pListWidget->setFixedSize(QSize(470, 150)); for (const auto& jobName: m_pJobNames) { // std::shared_ptr<QListWidgetItem> listWidgetItem = std::make_shared<QListWidgetItem>(QString::fromStdString(jobName)); QListWidgetItem* listWidgetItem = new QListWidgetItem(m_pListWidget); QCustomListWidgetItem* customListWidget = new QCustomListWidgetItem(jobName, m_pListWidget); listWidgetItem->setSizeHint(customListWidget->size()); listWidgetItem->setFlags(listWidgetItem->flags() & ~Qt::ItemIsSelectable); m_pListWidget->addItem(listWidgetItem); m_pListWidget->setItemWidget(listWidgetItem, customListWidget); } } void UploadJobListDialog::removeit(size_t ui) { std::lock_guard<std::mutex> lock(a); for (int i = 0; i < m_pListWidget->count(); ++i) { sleep(10); QListWidgetItem* item = m_pListWidget->item(0); if (!item) continue; QCustomListWidgetItem* widget = dynamic_cast<QCustomListWidgetItem*>(m_pListWidget->itemWidget(item)); if (!widget) continue; int nRow = m_pListWidget->row(item); QListWidgetItem* pDeleteItem = m_pListWidget->takeItem(nRow); if (pDeleteItem != NULL) { delete pDeleteItem; } } } int main(int argc, char *argv[]) { QApplication a(argc, argv); std::vector<std::string> jobs = {"1","2","3","4","5"}; static UploadJobListDialog obj(jobs); std::thread([=] { obj.removeit(jobs.size()); } ).detach(); obj.exec(); return 0; }Questions:
- What is leading to corruption?
- Am I doing something wrong?
Ps: I am new to QT, any help is greatly appreciated.
@Krpadia123 said in [QT6][C++] Deleting item from Custom ListWidgetItem corrupting other entry in QT:
std::lock_guardstd::mutex lock(a);
You should use signals/slots between threads in Qt, then there is no need for synchronisation. It is not supported to manipulate UI from other threads than the UI thread!
Your other thread should emit a signal with the item index to delete as parameter. In your dialog make UploadJobListDialog::removeit(size_t ui) a slot. Then connect the signal with slot. When the other thread wants to delete an item it simply emits the signal. -
@jsulm Thank you soo much, its working perfectly with signal/slots.
Thank you again!