Close ItemDeligate in View when some other Widget is clicked



  • Hello,

    what signal can I use to close the current editor of a QAbstractItemView derived class when I click somewhere else on the ui.
    Of course I can connect a signal from every Widget if it is clicked to the closeEditorSlot, but there must be a better way?


  • Moderators

    @gde23
    what type of editor?
    Actually thats normal behavior you trying to achieve. When the editor widget receives focus and then an focus out the editor is closed. Unless you have some custom composed editor or some other special properties set?



  • @raven-worx
    It is a QTreeView, that has a QStyledItemDelegate in it which may be a QLineEdit for example. Now when I start editing the cursor appears in the QLineEditDelegate and I can edit it. However when I'm done editing I have to confirm it by pressig enter or clicking somewhere else in the QTreeView.
    Clicking some other Widget in the UI or somwhere else on the mainwindow does not close the editor.
    Maybe I have some Signal/Slot connection with the Delegate missing?


  • Lifetime Qt Champion

    Hi,

    Is it a custom QStyledItemDelegate ?



  • There should be nothing to code at all to obtain the behaviour you describe.

    • Can you show us your delegate's code?
    • Are you subclassing the view as well?


  • @SGais, yes it is a custom delegate.

    Here is my code:

    MyDelegate::MyDelegate(QObject *parent)
        : QStyledItemDelegate(parent)
    {
    
    }
    
    QWidget *MyDelegate::createEditor(QWidget *parent,
        const QStyleOptionViewItem &/* option */,
        const QModelIndex &index ) const
    {
        QWidget *editor;
        QVariant is_checkable = index.model()->data(index, Qt::CheckStateRole);
       
        editor = new QLineEdit(parent);
    
        // if it is checkable add a checkbox
        if(is_checkable.isValid())
        {
            QWidget* widget = new QWidget(parent);
            QHBoxLayout* layout = new QHBoxLayout();
            // to align it with the original one
            layout->setSpacing(3);
            layout->setContentsMargins(3, 0, 0, 0);
    
            QCheckBox* check = new QCheckBox();
            widget->setLayout(layout);
            layout->addWidget(check);
            layout->addWidget(editor);
            widget->setAutoFillBackground(true);
            return widget;
        }
        else
        {
            return editor;
        }
    }
    
    void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
    {    
        QString value = index.model()->data(index, Qt::EditRole).toString();
        if(dynamic_cast<QLineEdit*>(editor) == NULL)
        {
            QLineEdit* lineEdit = editor->findChild<QLineEdit*>();
            lineEdit->setText(value);
            lineEdit->setCursorPosition(0); // move cursor to left so we see not only the last decimals but the beginning
            QCheckBox *check = editor->findChild<QCheckBox*>();
            check->setChecked(index.model()->data(index, Qt::CheckStateRole).toBool());
            return;
        }
        else
        {
            QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
            lineEdit->setText(value);
            return;
        }    
    }
    
    void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        QCheckBox* check = editor->findChild<QCheckBox*>();
        if(check != NULL)
        {
            Qt::CheckState value = check->checkState();
            model->setData(index, value, Qt::CheckStateRole);
        }
        
        if(dynamic_cast<QLineEdit*>(editor) == NULL)
        {
            QLineEdit* lineEdit = editor->findChild<QLineEdit*>();
            QString value = lineEdit->text();
            model->setData(index, value, Qt::EditRole);
            break;
        }
        else
        {
            QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
            QString value = lineEdit->text();
            model->setData(index, value, Qt::EditRole);
            return;
        }  
    }
    
    void MyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
    {
        editor->setGeometry(option.rect);
    }
    

  • Moderators

    @gde23
    and i guess it isn't working for editors which are created with a lineedit and checkbox?

    As i said when the editor widget (the pointer returned from createEditor()) receives a focus-out event the editor is closed. Since you compose a editor widget the sub-widget receives the focus-out event without the QStyledItemDelegate recognizing it.

    So you need to make sure that the container widget receives a focus-out event or to close the editor yourself.



  • I have checked it and it looks like when you edit a ItemDelegate in some cell of in my case the tableView and after you move the mouse arrow to QMainWindow and you clicked once or double then looks like the itemDelegate in the cell does not lose its focus even you resize the main widow. It loses its focus when you click on other widget located on the gui of QMainWindow.
    0_1542884444364_Part.jpg



  • Can I ask why are you doing this? a QLineEdit and a checkbox is already what you get from the default of QStyledItemDelegate



  • @raven-worx no it does not work for both cases (with/without the container widget)
    @VRonin: I have tow QTreeViews in the mainwindow. When i click the other QTreeView (or the QTableView that i have in the UI) the editor closes, however clicking some other Widget (e.g. a Button) does not close it
    To your second Question: I'm doing this since I want to add some more features to the Delegate like QSpinBoxes later depending on the type of data a item stores.



  • @gde23 said in Close ItemDeligate in View when some other Widget is clicked:

    like QSpinBoxes later depending on the type of data a item stores

    Again, QStyledItemDelegate already does this by default. You can customise it with QItemEditorFactory and you get the checkbox feature for free as well



  • @VRonin: what I need at the end is depending on the Item: QSpinbox or QComboBox or QLineEdit (and maybe some more like a QCombobox besides the QLineEdit in a single cell) depending on the data type the item stores.
    Can this all be done with the QItemEditorFactory? Then I'll take a look at it.
    EDIT: as far as I could find out QItemEditorFactory cannot provide a QComboBox for a Item that has multiple choice kind of content (std::map with several entries)
    EDIT2: so there seems to be some other thing going on. The QTreeView is in a Dockwidget and when I place some pushbutton inside the QDockWidgetContente besides the QTreeView and I press it the editor is closed as it should. However when I click some pushbutton on the MainWindow it is not closed.



  • Ok i found out that the problem is somwhere totally else and has nothing to do with the Delegate or the DockWidgets.

    All my buttons are QToolButtons. When they are clicked the editor does not close.
    However a QPushButton or also another Widget will close it as

    I have added these two button to the UI

        centralWidget()->layout()->addWidget(new QToolButton(centralWidget()));
        centralWidget()->layout()->addWidget(new QPushButton(centralWidget()));
    

    clicking the second one closes the editor in the view. However closing the first one does not.

    Even more it does not have to do with the view at all. Just a Mainwindow with a QToolButton a QLineEdit and a QPushbutton will demonstrate the behavior.


  • Moderators

    @gde23
    you can change this behavior by calling setFocusPolicy(Qt::StrongFocus) on the QToolButton
    By default QToolButtons only have TabFocus set, whereas QPushButtons don't



  • Thanks a lot. That solves the problem.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.