QListWidget doesn't show properly custom QWidget
-
Hi VRonin,
First of all, thanks for your help. The document you linked has been very usefull. I have been trying to subclass the Qstyle delegate as it states there, but I'm still having some problems to display the custom widget. I think that the problem is on how I reimplemented the paint function, because, to be honest, It was some kind of empirical try (my bad). So here is the code:
FilterWindow.h (custom class and delegate inside)
#ifndef FILTERWINDOW_H #define FILTERWINDOW_H #include <QtCore/QVariant> #include <QtWidgets/QAction> #include <QtWidgets/QApplication> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QCheckBox> #include <QtWidgets/QFrame> #include <QtWidgets/QHeaderView> #include <QtWidgets/QPushButton> #include <QtWidgets/QTableWidget> #include <QtWidgets/qstyleditemdelegate.h> #include <QtGui/qpainter.h> #include <QtWidgets> class FilterWindow : public QWidget { Q_OBJECT public: FilterWindow(QWidget *parent = 0); FilterWindow(QWidget *, std::string, std::vector<std::string>); FilterWindow(const FilterWindow &); void paint(QPainter *painter, const QRect &rect, const QPalette &palette) const; QSize sizeHint() const; void setList(std::vector<std::string>); void setTittle(std::string tittle); private slots: void pressArrow(); void apply(); void reset(); void checkMark(); signals: void applyPressed(std::vector<std::string>); private: void setUi(QWidget *parent); void setUi(QWidget *parent, std::string tittle); QFrame *Frame; QCheckBox *checkBox; QPushButton *ArrowBtn; QTableWidget *Table; QPushButton *ResetBtn; QPushButton *AplyBtn; bool open; std::vector<std::string> list; std::string tittle; }; class customQStyledItemDelegate : public QStyledItemDelegate { Q_OBJECT public: customQStyledItemDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; Q_DECLARE_METATYPE(FilterWindow) #endif //FILTERWINDOW_H
FilterWindow.cpp
FilterWindow::FilterWindow(QWidget *parent) { open = false; list.clear(); setUi(parent); Frame->setFixedSize(281, 35); ArrowBtn->setEnabled(false); connect(ArrowBtn, SIGNAL(released()), this, SLOT(pressArrow())); connect(ResetBtn, SIGNAL(released()), this, SLOT(reset())); connect(AplyBtn, SIGNAL(released()), this, SLOT(apply())); connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(checkMark())); } FilterWindow::FilterWindow(QWidget *parent, std::string tittle, std::vector<std::string> _list) { setUi(parent, tittle); setList(_list); this->tittle = tittle; Frame->setFixedSize(281, 35); open = false; ArrowBtn->setEnabled(false); connect(ArrowBtn, SIGNAL(released()), this, SLOT(pressArrow())); connect(ResetBtn, SIGNAL(released()), this, SLOT(reset())); connect(AplyBtn, SIGNAL(released()), this, SLOT(apply())); connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(checkMark())); } FilterWindow::FilterWindow(const FilterWindow &input) { setUi(input.parentWidget(), input.tittle); list.clear(); list = input.list; this->tittle = input.tittle; Frame->setFixedSize(281, 35); open = false; ArrowBtn->setEnabled(false); } void FilterWindow::setList(std::vector<std::string> _List) { list.clear(); Table->clear(); list = _List; Table->verticalHeader()->setHidden(true); Table->horizontalHeader()->setHidden(true); Table->setRowCount(list.size()); Table->setColumnCount(2); Table->setShowGrid(false); Table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); Qt::ItemFlags eFlags; eFlags = Qt::ItemIsEnabled; eFlags &= ~Qt::ItemIsEditable;; for (int i = 0; i < list.size(); i++) { Table->setCellWidget(i, 0, new QCheckBox()); ((QCheckBox*)(Table->cellWidget(i, 0)))->setChecked(true); Table->setItem(i, 1, new QTableWidgetItem(list.at(i).c_str())); Table->item(i, 1)->setFlags(eFlags); } Table->resizeColumnsToContents(); Table->resizeRowsToContents(); Table->setSelectionMode(QAbstractItemView::SelectionMode::NoSelection); Table->setFocusPolicy(Qt::FocusPolicy::NoFocus); } QSize FilterWindow::sizeHint() const { return QSize(281, 35); } void FilterWindow::paint(QPainter *painter, const QRect &rect, const QPalette &palette) const { Frame->repaint(rect); ArrowBtn->repaint(rect); checkBox->repaint(rect); Table->repaint(rect); ResetBtn->repaint(rect); AplyBtn->repaint(rect); } //PRIVATE FUNCTIONS void FilterWindow::setUi(QWidget *parent) { Frame = new QFrame(parent); Frame->setObjectName(QStringLiteral("Frame")); Frame->setFixedWidth(281); Frame->setFixedHeight(89); Frame->setStyleSheet(QLatin1String("QFrame\n" "{\n" " border-style: solid;\n" " border-size: 0px;\n" " border-radius: 4px;\n" " border-color: transparent;\n" "}")); Frame->setFrameShape(QFrame::StyledPanel); Frame->setFrameShadow(QFrame::Raised); checkBox = new QCheckBox(Frame); checkBox->setObjectName(QStringLiteral("checkBox")); checkBox->setGeometry(QRect(0, 0, 248, 35)); checkBox->setAutoFillBackground(false); checkBox->setStyleSheet(QLatin1String("QCheckBox\n" "{\n" " background-color: rgb(128,139,143);\n" " color: white;\n" " border-radius: 4px;\n" " padding-left: 8px;\n" "}\n" "\n" "QCheckBox::indicator:unchecked {\n" " image: url(:/OptiNanoPro/uchk);\n" "}\n" "\n" "\n" "QCheckBox::indicator:checked {\n" " image: url(:/OptiNanoPro/chk);\n" "}\n" "")); checkBox->setChecked(false); ArrowBtn = new QPushButton(Frame); ArrowBtn->setObjectName(QStringLiteral("ArrowBtn")); ArrowBtn->setGeometry(QRect(246, 0, 36, 35)); ArrowBtn->setAutoFillBackground(true); QIcon icon; icon.addFile(QStringLiteral(":/OptiNanoPro/DownArrwLd"), QSize(), QIcon::Normal, QIcon::Off); ArrowBtn->setIcon(icon); ArrowBtn->setIconSize(QSize(36, 35)); ArrowBtn->setFlat(true); Table = new QTableWidget(Frame); Table->setObjectName(QStringLiteral("Table")); Table->setGeometry(QRect(0, 35, 281, 36)); Table->setStyleSheet(QLatin1String("QTableWidget\n" "{\n" " background-color: white;\n" " border-radius: 0px;\n" "}\n" "QCheckBox\n" "{\n" " color: white;\n" " border-radius: 4px;\n" " padding-left: 8px;\n" "}\n" "\n" "QCheckBox::indicator:unchecked {\n" " image: url(:/OptiNanoPro/uchk);\n" "}\n" "\n" "\n" "QCheckBox::indicator:checked {\n" " image: url(:/OptiNanoPro/chk);\n" "}\n" "QTableWidgetItem\n" "{\n" " color: black;" "}\n")); ResetBtn = new QPushButton(Frame); ResetBtn->setObjectName(QStringLiteral("ResetBtn")); ResetBtn->setText(QStringLiteral("Reset")); ResetBtn->setGeometry(QRect(0, 66, 169, 23)); ResetBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); AplyBtn = new QPushButton(Frame); AplyBtn->setObjectName(QStringLiteral("AplyBtn")); AplyBtn->setText(QStringLiteral("Apply")); AplyBtn->setGeometry(QRect(169, 66, 111, 23)); AplyBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); } void FilterWindow::setUi(QWidget *parent,std::string tittle) { Frame = new QFrame(parent); Frame->setObjectName(QStringLiteral("Frame")); Frame->setFixedWidth(281); Frame->setFixedHeight(89); Frame->setStyleSheet(QLatin1String("QFrame\n" "{\n" " border-style: solid;\n" " border-size: 0px;\n" " border-radius: 4px;\n" " border-color: transparent;\n" "}")); Frame->setFrameShape(QFrame::StyledPanel); Frame->setFrameShadow(QFrame::Raised); Frame->setAttribute(Qt::WA_DeleteOnClose); checkBox = new QCheckBox(Frame); checkBox->setText(tittle.c_str()); checkBox->setObjectName(QStringLiteral("checkBox")); checkBox->setGeometry(QRect(0, 0, 248, 35)); checkBox->setAutoFillBackground(false); checkBox->setStyleSheet(QLatin1String("QCheckBox\n" "{\n" " background-color: rgb(128,139,143);\n" " color: white;\n" " border-radius: 4px;\n" " padding-left: 8px;\n" "}\n" "\n" "QCheckBox::indicator:unchecked {\n" " image: url(:/OptiNanoPro/uchk);\n" "}\n" "\n" "\n" "QCheckBox::indicator:checked {\n" " image: url(:/OptiNanoPro/chk);\n" "}\n" "")); checkBox->setChecked(false); ArrowBtn = new QPushButton(Frame); ArrowBtn->setObjectName(QStringLiteral("ArrowBtn")); ArrowBtn->setGeometry(QRect(246, 0, 36, 35)); ArrowBtn->setAutoFillBackground(true); QIcon icon; icon.addFile(QStringLiteral(":/OptiNanoPro/DownArrwLd"), QSize(), QIcon::Normal, QIcon::Off); ArrowBtn->setIcon(icon); ArrowBtn->setIconSize(QSize(36, 35)); ArrowBtn->setFlat(true); Table = new QTableWidget(Frame); Table->setObjectName(QStringLiteral("Table")); Table->setGeometry(QRect(0, 35, 281, 31)); Table->setStyleSheet(QLatin1String("QTableWidget\n" "{\n" " background-color: white;\n" " border-radius: 0px;\n" "}")); ResetBtn = new QPushButton(Frame); ResetBtn->setObjectName(QStringLiteral("ResetBtn")); ResetBtn->setGeometry(QRect(0, 66, 169, 23)); ResetBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); AplyBtn = new QPushButton(Frame); AplyBtn->setObjectName(QStringLiteral("AplyBtn")); AplyBtn->setGeometry(QRect(169, 66, 111, 23)); AplyBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); } //SLOTS void FilterWindow::pressArrow() { if (open) //It was opened { ArrowBtn->setIcon(QIcon(":/OptiNanoPro/DownArrwLd")); Frame->setFixedSize(281, 35); } else //It was closed { ArrowBtn->setIcon(QIcon(":/OptiNanoPro/UpArrwLd")); Frame->setFixedSize(281, 89); } open = !open; } void FilterWindow::apply() { std::vector<std::string> list_out; for (int i = 0; i < Table->rowCount(); i++) { if (((QCheckBox*)(Table->cellWidget(i, 0)))->isChecked()) { list_out.push_back(Table->item(i,1)->text().toStdString()); } } emit applyPressed(list_out); } void FilterWindow::reset() { for (int i = 0; i < Table->rowCount(); i++) { ((QCheckBox*)(Table->cellWidget(i, 0)))->setChecked(true); } } void FilterWindow::checkMark() { if (checkBox->isChecked()) { ArrowBtn->setEnabled(true); } else { ArrowBtn->setIcon(QIcon(":/OptiNanoPro/DownArrwLd")); Frame->setFixedSize(281, 35); open = false; ArrowBtn->setEnabled(false); } } //Delegate void customQStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.data().canConvert<FilterWindow>()) { FilterWindow filt = qvariant_cast<FilterWindow>(index.data()); filt.paint(painter, option.rect, option.palette); } else { QStyledItemDelegate::paint(painter, option, index); } } QSize customQStyledItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
And that's what I'm doing:
ui.LoadConfTable->setItemDelegate(new customQStyledItemDelegate); //Add delegate QListWidgetItem * myItem = new QListWidgetItem(); wndw = new FilterWindow(ui.LoadFrame, "Serial Number", cfg.serialNumber); //Create a FilterWindow myItem->setSizeHint(QSize(281, 89)); myItem->setData(0, QVariant::fromValue(*wndw)); //The tutorial settled that it should be casted to QVariant to save it in an item ui.LoadConfTable->addItem(myItem); //And just after this it should be painted?
This is how it looks like:
-
Not quite there yet, the widget is not the data. The data should be what's in the widget.
take a look at AQP page 193. They use a QLabel as a delegate but its basically the same in your case (just as disclaimer: I don't like that example as it's inefficient, you should paint directly the delegate, not use a separate QWidget but it works and it's a good enough start)
-
Good morning,
Thank you so much for your advice. After getting stucked in some points and trying to understand the QStyledItemDelegate overrided functions I managed to draw perfectly the widgets inside a QTableWidget . So after achieve that, I started to implement the item edition part getting some odd bugs. Here is the curent code:
FilterWindow.h
#ifndef FILTERWINDOW_H #define FILTERWINDOW_H #include <QtWidgets/QStyledItemDelegate> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QCheckBox> #include <QtWidgets/QFrame> #include <QtWidgets/QHeaderView> #include <QtWidgets/QPushButton> #include <QtWidgets/QTableWidget> #include <QtWidgets/QTableView> #include <QWidget> #include <QPainter> class FilterWindow : public QWidget { Q_OBJECT public: explicit FilterWindow(QWidget* parent = NULL); FilterWindow(QWidget* parent, std::string); FilterWindow(FilterWindow&); ~FilterWindow(); void setUi(QWidget* parent, std::string tittle); void press(); void setData(std::string, std::vector<std::string> = std::vector<std::string>(), int rw = -1); //Overrided QSize size() const; void render(QPaintDevice * target, const QPoint & targetOffset = QPoint(), const QRegion & sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren)); signals: void btnprsd(int row, bool prsd); public slots: void pressedSlot(); private: QFrame* Frame; QCheckBox* checkBox; QPushButton* ArrowBtn; QTableWidget* Table; QPushButton* ResetBtn; QPushButton* AplyBtn; std::vector<std::string> list; int rw; bool pressed; }; class FilterWindowDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit FilterWindowDelegate(QObject* parent); ~FilterWindowDelegate(); void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem &option, const QModelIndex&) const; void updateEditorGeometry(QWidget*, const QStyleOptionViewItem&, const QModelIndex&) const; void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; void setEditorData(QWidget * editor, const QModelIndex & index) const; void insertElement(std::string tittle, std::vector<std::string> = std::vector<std::string>()); public slots: void btn_pressed(int row, bool prsd); private: //Vars std::vector<FilterWindow*> FrmWindows; //Others QTableWidget* prnt; }; #endif //FILTERWINDOW_H
FilterWindow.cpp
#include <filterwindow.h> ///Filter window //Public Functions FilterWindow::FilterWindow(QWidget* parent) : QWidget(parent) { setUi(parent, ""); pressed = false; press(); connect(ArrowBtn, SIGNAL(pressed()), this, SLOT(pressedSlot())); } FilterWindow::FilterWindow(QWidget* parent, std::string ttle) { setUi(parent, ttle); pressed = false; press(); connect(ArrowBtn, SIGNAL(pressed()), this, SLOT(pressedSlot())); } FilterWindow::FilterWindow(FilterWindow& in) { setUi(in.Frame->parentWidget(), in.checkBox->text().toStdString()); pressed = false; press(); rw = in.rw; connect(ArrowBtn, SIGNAL(pressed()), this, SLOT(pressedSlot())); } FilterWindow::~FilterWindow() { delete Frame; delete checkBox; delete ArrowBtn; delete Table; delete ResetBtn; delete AplyBtn; } void FilterWindow::setUi(QWidget* parent, std::string tittle) { Frame = new QFrame(parent); Frame->setObjectName(QStringLiteral("Frame")); Frame->setFixedWidth(281); Frame->setFixedHeight(89); Frame->setStyleSheet(QLatin1String("QFrame\n" "{\n" " border-style: solid;\n" " border-size: 0px;\n" " border-radius: 4px;\n" " border-color: transparent;\n" "}")); Frame->setFrameShape(QFrame::StyledPanel); Frame->setFrameShadow(QFrame::Raised); Frame->setAttribute(Qt::WA_DeleteOnClose); checkBox = new QCheckBox(Frame); checkBox->setText(tittle.c_str()); checkBox->setObjectName(QStringLiteral("checkBox")); checkBox->setGeometry(QRect(0, 0, 248, 35)); checkBox->setAutoFillBackground(false); checkBox->setStyleSheet(QLatin1String("QCheckBox\n" "{\n" " background-color: rgb(128,139,143);\n" " color: white;\n" " border-radius: 4px;\n" " padding-left: 8px;\n" "}\n" "\n" "QCheckBox::indicator:unchecked {\n" " image: url(:/OptiNanoPro/uchk);\n" "}\n" "\n" "\n" "QCheckBox::indicator:checked {\n" " image: url(:/OptiNanoPro/chk);\n" "}\n" "")); checkBox->setChecked(false); ArrowBtn = new QPushButton(Frame); ArrowBtn->setObjectName(QStringLiteral("ArrowBtn")); ArrowBtn->setGeometry(QRect(246, 0, 36, 35)); ArrowBtn->setAutoFillBackground(true); QIcon icon; icon.addFile(QStringLiteral(":/OptiNanoPro/DownArrwLd"), QSize(), QIcon::Normal, QIcon::Off); ArrowBtn->setIcon(icon); ArrowBtn->setIconSize(QSize(36, 35)); ArrowBtn->setFlat(true); Table = new QTableWidget(Frame); Table->setObjectName(QStringLiteral("Table")); Table->setGeometry(QRect(0, 35, 281, 31)); Table->setStyleSheet(QLatin1String("QTableWidget\n" "{\n" " background-color: white;\n" " border-radius: 0px;\n" "}")); ResetBtn = new QPushButton(Frame); ResetBtn->setText("Reset"); ResetBtn->setObjectName(QStringLiteral("ResetBtn")); ResetBtn->setGeometry(QRect(0, 66, 169, 23)); ResetBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); AplyBtn = new QPushButton(Frame); AplyBtn->setText("Apply"); AplyBtn->setObjectName(QStringLiteral("AplyBtn")); AplyBtn->setGeometry(QRect(169, 66, 111, 23)); AplyBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); } void FilterWindow::press() { if (pressed) { Frame->setFixedHeight(89); ArrowBtn->setIcon(QIcon(":/OptiNanoPro/UpArrwLd")); } else { Frame->setFixedHeight(35); ArrowBtn->setIcon(QIcon(":/OptiNanoPro/DownArrwLd")); } } void FilterWindow::setData(std::string name, std::vector<std::string> _list, int _rw) { if (!name.empty()) { checkBox->setText(name.c_str()); } if (!list.empty()) { list = _list; } if (rw != -1) { rw = _rw; } } QSize FilterWindow::size() const { return Frame->size(); } void FilterWindow::render(QPaintDevice * target, const QPoint & targetOffset, const QRegion & sourceRegion, RenderFlags renderFlags) { Frame->render(target); } //Slots void FilterWindow::pressedSlot() { pressed = !pressed; press(); emit(btnprsd(rw,pressed)); } ///Filter Window Delegate //PUBLIC FUNCTIONS FilterWindowDelegate::FilterWindowDelegate(QObject* parent) : QStyledItemDelegate(parent) { prnt = qobject_cast<QTableWidget*>(parent); FrmWindows.clear(); } FilterWindowDelegate::~FilterWindowDelegate() { FrmWindows.clear(); } void FilterWindowDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QPixmap pixmap(FrmWindows.at(index.row())->size()); FrmWindows.at(index.row())->render(&pixmap); painter->drawPixmap(option.rect.x(),option.rect.y(), pixmap); prnt->setRowHeight(index.row(), FrmWindows.at(index.row())->size().height() + 1); } ////AQUI EXTRAER EL QWIDGET DEL INDICE Y DEVOLVERLO PARA QUE PERMITA ACTUALIZAR LOS VALORES. TERMINAR MAÑANA!!!!! QWidget* FilterWindowDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem &option, const QModelIndex&idx) const { return new FilterWindow(*FrmWindows.at(idx.row())); } void FilterWindowDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& idx) const { editor->setGeometry(option.rect); } void FilterWindowDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { } void FilterWindowDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const { } void FilterWindowDelegate::insertElement(std::string tittle, std::vector<std::string> _list) { //Internal part FrmWindows.push_back(new FilterWindow(prnt, tittle)); FrmWindows.at(FrmWindows.size() - 1)->setData(tittle, _list, FrmWindows.size() - 1); //Conect widget signal with delegate to resize rows connect(FrmWindows.at(FrmWindows.size() - 1), SIGNAL(btnprsd(int, bool)), this, SLOT(btn_pressed(int, bool))); //External part prnt->insertRow(FrmWindows.size()-1); } //Slots void FilterWindowDelegate::btn_pressed(int row, bool prsd) { if (prsd) { prnt->setRowHeight(row, 90); } else { prnt->setRowHeight(row, 36); } }
And that's is how I call it:
fltr = new FilterWindowDelegate(ui.LoadConfTable); ui.LoadConfTable->setItemDelegate(fltr); ui.LoadConfTable->setRowCount(0); ui.LoadConfTable->setColumnCount(1); ui.LoadConfTable->verticalHeader()->setHidden(true); ui.LoadConfTable->horizontalHeader()->setHidden(true); ui.LoadConfTable->setColumnWidth(0, 282); ui.LoadConfTable->setShowGrid(false); ui.LoadConfTable->setRowHeight(0, 36); fltr->insertElement("HOLA"); fltr->insertElement("ADIOS");
So with all this code, this is how i get it
By some reason, it selects the last item and starts an editor placed in a wrong position. (I'm aware that is not an optimal code)
Once more, thanks for your help. This book has been a good resource to improve my skills,
José
-
I would have many comments on the implementation but for now let's leave them in the drawer.
return new FilterWindow(*FrmWindows.at(idx.row()));
should becomereturn FrmWindows.at(idx.row());
.
Don't return a copy (that you can't do anyway) but the widget itself -
It's still having the same bug. The upper windget is the editor of the second element in the table, which it appears by default even whitout selecting that element and appears at this place (The right place would be the second row of the table and whitout that skew if it would have been called)
-
I solved this. It seems as if the TableWidget is not cleared before starting to add items it keeps some residual widgets (weird behaviour) . Now I'm getting what I think that is the last error with this issue. When I click in a table row to edit one of the widgets, it happens this:
1st - Editor called 2nd - Someone calls the widget destructor throwed as editor (internal signal) 3rd - Tries to paint it (Obviously it crashes)
Here is the call stack
!FilterWindow::~FilterWindow() Línea 28 C++
[External Code]
Qt5Cored.dll!qDeleteInEventHandler(QObject * o) Línea 4552 C++
Qt5Cored.dll!QObject::event(QEvent * e) Línea 1255 C++
Qt5Widgetsd.dll!QWidget::event(QEvent * event) Línea 9220 C++
Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Línea 3745 C++
Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Línea 3708 C++ -
After some headache days I found the problem. The FilterWindow widget had set wrong the parent in children widgets, so, the right way would be :
void FilterWindow::setUi(std::string tittle) { Frame = new QFrame(this); //Here it must be this, to set the widget itself as the parent Frame->setObjectName(QStringLiteral("Frame")); Frame->setFixedWidth(281); Frame->setFixedHeight(89); Frame->setStyleSheet(QLatin1String("QFrame\n" "{\n" " border-style: solid;\n" " border-width: 0px;\n" " border-radius: 4px;\n" " border-color: transparent;\n" "}")); Frame->setFrameShape(QFrame::StyledPanel); Frame->setFrameShadow(QFrame::Raised); Frame->setAttribute(Qt::WA_DeleteOnClose); checkBox = new QCheckBox(Frame); checkBox->setText(tittle.c_str()); checkBox->setObjectName(QStringLiteral("checkBox")); checkBox->setGeometry(QRect(0, 0, 248, 35)); checkBox->setAutoFillBackground(false); checkBox->setStyleSheet(QLatin1String("QCheckBox\n" "{\n" " background-color: rgb(128,139,143);\n" " color: white;\n" " border-radius: 4px;\n" " padding-left: 8px;\n" "}\n" "\n" "QCheckBox::indicator:unchecked {\n" " image: url(:/OptiNanoPro/uchk);\n" "}\n" "\n" "\n" "QCheckBox::indicator:checked {\n" " image: url(:/OptiNanoPro/chk);\n" "}\n" "")); checkBox->setChecked(true); ArrowBtn = new QPushButton(Frame); ArrowBtn->setObjectName(QStringLiteral("ArrowBtn")); ArrowBtn->setGeometry(QRect(246, 0, 36, 35)); ArrowBtn->setAutoFillBackground(true); QIcon icon; icon.addFile(QStringLiteral(":/OptiNanoPro/DownArrwLd"), QSize(), QIcon::Normal, QIcon::Off); ArrowBtn->setIcon(icon); ArrowBtn->setIconSize(QSize(36, 35)); ArrowBtn->setFlat(true); Table = new QTableWidget(Frame); Table->setObjectName(QStringLiteral("Table")); Table->setGeometry(QRect(0, 35, 281, 31)); Table->setStyleSheet(QLatin1String("QTableWidget\n" "{\n" " background-color: white;\n" " border-radius: 0px;\n" "}" "\n" "QCheckBox\n" "{\n" " color: white;\n" " padding-left: 8px;\n" "}\n" "\n" "QCheckBox::indicator:unchecked {\n" " image: url(:/OptiNanoPro/uchk);\n" "}\n" "\n" "QCheckBox::indicator:checked {\n" " image: url(:/OptiNanoPro/chk);\n" "}\n" "")); ResetBtn = new QPushButton(Frame); ResetBtn->setText("Reset"); ResetBtn->setObjectName(QStringLiteral("ResetBtn")); ResetBtn->setGeometry(QRect(0, 66, 169, 23)); ResetBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); AplyBtn = new QPushButton(Frame); AplyBtn->setText("Apply"); AplyBtn->setObjectName(QStringLiteral("AplyBtn")); AplyBtn->setGeometry(QRect(169, 66, 111, 23)); AplyBtn->setStyleSheet(QLatin1String("QPushButton\n" "{\n" " background-color: white;\n" " border-width: 1px;\n" " border-style: solid;\n" " border-color: rgb(86,86,84);\n" " border-radius: 3px;\n" " color: rgb(86,86,84);\n" "}")); }