Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QStyledItemDelegate highlighting Indentation space on focus?
Forum Updated to NodeBB v4.3 + New Features

QStyledItemDelegate highlighting Indentation space on focus?

Scheduled Pinned Locked Moved Solved General and Desktop
qt c++delegatehelpproblemqtreeview
19 Posts 5 Posters 2.2k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S StudentScripter

    So i created my QStyledItemDelegate and actually highlighting the delegate does work, but the identation space of my QTreeView stays white. I want the identationspace to get highlighted too.

    Here is how it looks like right now: febae6c7-5d1c-4ead-acc5-fb2bb0a8a9fa-image.png

    Ps: it would be even better if the identation space would be gone if there is no item grouped below, but still the whole entry should be highlighted blue.

    Here is my code for the delegate, please help me:
    .cpp:

    #include "ViewLayerItemDelegate.h"
    #include <QStyledItemDelegate>
    #include <QPainter>
    #include <QApplication>
    
    
    
    
    ViewLayerItemDelegate::ViewLayerItemDelegate(QObject *parent)
        : QStyledItemDelegate{parent}
    {
    
    }
    
    
    
    QWidget *ViewLayerItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        qDebug() << "Editor created";
        
        LineEditCheckBoxWidget *editor = new LineEditCheckBoxWidget(parent);
        if (option.state & QStyle::State_Selected) {
            //editor->setStyleSheet("background-color: lightblue;");
        }
    
       // Verbinden Sie das textChanged() Signal des LineEdits mit Ihrem Slot
        connect(editor->lineEdit, &QLineEdit::textChanged, this, &ViewLayerItemDelegate::onLineEditTextChanged);
    
    
    
        return editor;
    }
    
    
    
    
    void ViewLayerItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
    {
    
        
        LineEditCheckBoxWidget *widget = static_cast<LineEditCheckBoxWidget *>(editor);
    
        // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten
        QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
        bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
    
        widget->lineEdit->setText(lineEditvalue);
        widget->checkBox->setChecked(checkBoxValue);
        
        
    
    
        widget->lineEdit->setFocus(Qt::MouseFocusReason); // Editor aktivieren
        widget->lineEdit->setStyleSheet("");
        widget->iconLabel->setAttribute(Qt::WA_TranslucentBackground);
        widget->setStyleSheet("background: white");
            
    }
    
    
    
    
    void ViewLayerItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
    {
        
        
        LineEditCheckBoxWidget *widget = static_cast<LineEditCheckBoxWidget *>(editor);
    
        
    
        // Speichern Sie die Werte der SpinBox und CheckBox im Modell
        QString lineEditvalue = widget->lineEdit->text();
        bool checkBoxValue = widget->checkBox->isChecked();
    
        model->setData(index, lineEditvalue, Qt::EditRole);
        model->setData(index, checkBoxValue ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
        
        qDebug() << "Model data set";
    }
    
    
    
    
    void ViewLayerItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        editor->setGeometry(option.rect);
    }
    
    
    
    
    QSize ViewLayerItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        
        QSize size = QStyledItemDelegate::sizeHint(option, index);
            size.setHeight(40); // Setzen Sie hier die gewünschte Höhe
        return size;
    }
    
    
    
    
    
    
    void ViewLayerItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);
    
        LineEditCheckBoxWidget widget;
    
        // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten
        QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
        bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
    
        widget.lineEdit->setText(lineEditvalue);
        widget.checkBox->setChecked(checkBoxValue);
    
        // Laden Sie das Icon und setzen Sie es auf das QLabel
        QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
        QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        widget.iconLabel->setPixmap(scaledPixmap);
    
       
    
        // Passen Sie das Aussehen des Widgets basierend auf der QStyleOptionViewItem an
        if (opt.state & QStyle::State_Selected) {
        
            widget.setStyleSheet("background-color: lightblue;");
            
        }else{
        qDebug() << "Test"; 
        widget.setStyleSheet("background-color: white");
        }
    
        widget.resize(option.rect.size()); // Stellen Sie sicher, dass die Größe des Widgets der Größe des Elements entspricht
    
        // Rendern Sie das Widget in den Painter
        QPixmap pixmap(widget.size());
        widget.render(&pixmap);
    
        // Zeichnen Sie das Pixmap mit dem QPainter
        painter->drawPixmap(option.rect.topLeft(), pixmap);
    }
    
    
    
    
    // Slot-Implementierung
    void ViewLayerItemDelegate::onLineEditTextChanged(const QString &text)
    {
        // Hier können Sie die gewünschte Aktion ausführen, wenn der Text im LineEdit bearbeitet wird
        qDebug() << "LineEdit text changed to:" << text;
    }
    
    
    
    
    
    
    
    
    
    void LineEditCheckBoxWidget::mousePressEvent(QMouseEvent *event)
    {
        qDebug() << "Test clicked";
    
        QWidget::mousePressEvent(event);
    }
    
    

    and here delegate.h:

    #ifndef VIEWLAYERITEMDELEGATE_H
    #define VIEWLAYERITEMDELEGATE_H
    
    #include <QStyledItemDelegate>
    #include <QModelIndex>
    #include <QObject>
    #include <QSize>
    #include <QLineEdit>
    #include <QStandardItemModel>
    #include <QCheckBox>
    #include <QFormLayout>
    #include <QLabel>
    #include <QPushButton>
    
    
    
    
    // Definieren Sie das benutzerdefinierte Widget
    class LineEditCheckBoxWidget : public QWidget {
        Q_OBJECT
    public:
        QLineEdit *lineEdit;
        QCheckBox *checkBox;
        QLabel *iconLabel;
    
    
        LineEditCheckBoxWidget(QWidget *parent = nullptr) : QWidget(parent) {
            QHBoxLayout *layout = new QHBoxLayout(this);
            layout->setContentsMargins(10,0,20,0);
            layout->setSpacing(0);
            lineEdit = new QLineEdit(this);
            checkBox = new QCheckBox(this);
            iconLabel = new QLabel(this);
    
    
            // Laden Sie das Icon und setzen Sie es auf das QLabel
            QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
            QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
            iconLabel->setPixmap(scaledPixmap);
    
    
    
            layout->addWidget(iconLabel);
            layout->addSpacing(10);
            layout->addWidget(lineEdit);
            layout->addStretch(1);
            layout->addWidget(checkBox);
    
            // Zugriff auf das QLineEdit-Widget und setzen Sie den Hintergrund transparent
            lineEdit->setStyleSheet("background: transparent;");
            lineEdit->setFrame(false);
            lineEdit->setPlaceholderText("<Empty>");
    
            checkBox->setStyleSheet("background: transparent");
        }
        
        // QWidget interface
    protected:
        void mousePressEvent(QMouseEvent *event) override;
        
    signals:
    
    };
    
    
    
    
    
    
    
    class ViewLayerItemDelegate : public QStyledItemDelegate
    {
        Q_OBJECT
    public:
        explicit ViewLayerItemDelegate(QObject *parent = nullptr);
        
        
        
        QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
        void setEditorData(QWidget *editor, const QModelIndex &index) const override;
        void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
        void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
        
        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
        
        
        
    public slots:
        
        void onLineEditTextChanged(const QString &text);
    
    
    signals:
        
        
        
        
        
        
    
    };
       
    
    #endif // VIEWLAYERITEMDELEGATE_H
    
    

    Thanks for helping, really really appreciate that. <3

    Chris KawaC Offline
    Chris KawaC Offline
    Chris Kawa
    Lifetime Qt Champion
    wrote on last edited by Chris Kawa
    #3

    The delegate only paints items. The branch and indentation areas are not part of an item, so item delegate doesn't cover them. Depending on your needs you can have an item highlighted or an entire row. If you want entire row highlighted you need to let the view handle it.

    You can override QTreeView::drawBranches and QTreeView::drawRow to paint the entire row, not just the item area.

    S 1 Reply Last reply
    1
    • Chris KawaC Chris Kawa

      The delegate only paints items. The branch and indentation areas are not part of an item, so item delegate doesn't cover them. Depending on your needs you can have an item highlighted or an entire row. If you want entire row highlighted you need to let the view handle it.

      You can override QTreeView::drawBranches and QTreeView::drawRow to paint the entire row, not just the item area.

      S Offline
      S Offline
      StudentScripter
      wrote on last edited by
      #4

      @Chris-Kawa Thank you, i tried this approach but im getting quite wierd looking results when i group items below each other, like that:

      The group "headder" is selected:
      6fbb80af-11ab-4e0e-b829-aadf8dcae04e-image.png

      The grouped object is selected:
      837a6e50-3578-4a89-9bdc-176b97e82089-image.png

      Here is my code:

      #include "ViewLayerList.h"
      #include <QHBoxLayout>
      #include <QCheckBox>
      #include <QLabel>
      #include "ViewLayerLineEdit.h"
      #include <QMouseEvent>
      #include "resizablepixmapitem.h"
      #include "SignalManager.h"
      #include <QHeaderView>
      #include <QPushButton>
      #include "ViewLayerCustomItem.h"
      
      
      
      
      
      ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent)
          : QTreeView{parent}, scene_durchgereicht(scene)
      {
          setHeaderHidden(true);
          setRootIsDecorated(true);
      
      
      
      
      
      mydelegate = new ViewLayerItemDelegate(this);
      
      model = new QStandardItemModel(10,1,this);
      
      
      
      for(int row = 0; row < 10; ++row)
      {
          for(int col = 0; col < 1; ++col)
          {
              QModelIndex index = model->index(row, col, QModelIndex());
              model->setData(index, "");
            
             
          }
      
      }
      
      
      this->setModel(model);
      this->setItemDelegate(mydelegate);
      
      
      
       //QModelIndex index = model->index(0, 0);
       // this->openPersistentEditor(index);
      
      
      
      this->setDragDropMode(QAbstractItemView::InternalMove);
      this->setSelectionMode(QAbstractItemView::ExtendedSelection);
      this->setDragEnabled(true);
      this->setAcceptDrops(true);
      this->setDropIndicatorShown(true);
      
      
      
      }
      
      
      
      
      
      
      
      void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
      {
         
      
      
          QModelIndexList selectedIndexes = selectionModel()->selectedIndexes();
      
          for (const QModelIndex& selectedIndex : selectedIndexes) {
              if (selectedIndex.row() == index.row()) {
             
                  QRect indentRect = visualRect(index);
                  indentRect.setRight(options.rect.left());
                  painter->fillRect(indentRect, QColor(173, 216, 230)); 
                  break; 
              }
          }
         
          
           QTreeView::drawRow(painter, options, index); 
      }
      
      
      

      Thanks for helping me thus far, hope you can give me another hint. :)
      Best regards

      Chris KawaC 1 Reply Last reply
      0
      • S StudentScripter

        @Chris-Kawa Thank you, i tried this approach but im getting quite wierd looking results when i group items below each other, like that:

        The group "headder" is selected:
        6fbb80af-11ab-4e0e-b829-aadf8dcae04e-image.png

        The grouped object is selected:
        837a6e50-3578-4a89-9bdc-176b97e82089-image.png

        Here is my code:

        #include "ViewLayerList.h"
        #include <QHBoxLayout>
        #include <QCheckBox>
        #include <QLabel>
        #include "ViewLayerLineEdit.h"
        #include <QMouseEvent>
        #include "resizablepixmapitem.h"
        #include "SignalManager.h"
        #include <QHeaderView>
        #include <QPushButton>
        #include "ViewLayerCustomItem.h"
        
        
        
        
        
        ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent)
            : QTreeView{parent}, scene_durchgereicht(scene)
        {
            setHeaderHidden(true);
            setRootIsDecorated(true);
        
        
        
        
        
        mydelegate = new ViewLayerItemDelegate(this);
        
        model = new QStandardItemModel(10,1,this);
        
        
        
        for(int row = 0; row < 10; ++row)
        {
            for(int col = 0; col < 1; ++col)
            {
                QModelIndex index = model->index(row, col, QModelIndex());
                model->setData(index, "");
              
               
            }
        
        }
        
        
        this->setModel(model);
        this->setItemDelegate(mydelegate);
        
        
        
         //QModelIndex index = model->index(0, 0);
         // this->openPersistentEditor(index);
        
        
        
        this->setDragDropMode(QAbstractItemView::InternalMove);
        this->setSelectionMode(QAbstractItemView::ExtendedSelection);
        this->setDragEnabled(true);
        this->setAcceptDrops(true);
        this->setDropIndicatorShown(true);
        
        
        
        }
        
        
        
        
        
        
        
        void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
        {
           
        
        
            QModelIndexList selectedIndexes = selectionModel()->selectedIndexes();
        
            for (const QModelIndex& selectedIndex : selectedIndexes) {
                if (selectedIndex.row() == index.row()) {
               
                    QRect indentRect = visualRect(index);
                    indentRect.setRight(options.rect.left());
                    painter->fillRect(indentRect, QColor(173, 216, 230)); 
                    break; 
                }
            }
           
            
             QTreeView::drawRow(painter, options, index); 
        }
        
        
        

        Thanks for helping me thus far, hope you can give me another hint. :)
        Best regards

        Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by Chris Kawa
        #5

        @StudentScripter This condition is wrong:

        if (selectedIndex.row() == index.row())
        

        Note that the first top level item has row == 0 and every first child of any item also has row == 0 ans so on, so that's why you see multiple items colored. You don't need to retrieve the entire list of selected items and loop over them. That's wasteful. It's enough to check if the index you're given is selected:

        void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
        {
            if (selectionModel()->isSelected(index)) {
               ...
        

        Also instead of having the delegate color selected item and the view color the remainder of the space you can just remove selection painting from the delegate and let the view paint it for entire row. You wouldn't have to get the visualRect and do the painting twice in parts. A lot of unnecessary calculations omitted.

        S 1 Reply Last reply
        1
        • Chris KawaC Chris Kawa

          @StudentScripter This condition is wrong:

          if (selectedIndex.row() == index.row())
          

          Note that the first top level item has row == 0 and every first child of any item also has row == 0 ans so on, so that's why you see multiple items colored. You don't need to retrieve the entire list of selected items and loop over them. That's wasteful. It's enough to check if the index you're given is selected:

          void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
          {
              if (selectionModel()->isSelected(index)) {
                 ...
          

          Also instead of having the delegate color selected item and the view color the remainder of the space you can just remove selection painting from the delegate and let the view paint it for entire row. You wouldn't have to get the visualRect and do the painting twice in parts. A lot of unnecessary calculations omitted.

          S Offline
          S Offline
          StudentScripter
          wrote on last edited by
          #6

          @Chris-Kawa said in QStyledItemDelegate highlighting Indentation space on focus?:

          First of all: Thank you very much, made me instantly happy this morning when i saw that i received an answer. :)

          I improved the if statement and it works perfectly fine, however i don't get the second part of your answer.
          I tried removing this part from my delegates paint method:

          /*
              // Passen Sie das Aussehen des Widgets basierend auf der QStyleOptionViewItem an
              if (opt.state & QStyle::State_Selected) {
              
                  widget.setStyleSheet("background-color: lightblue;");
                  
              }else{
          
              widget.setStyleSheet("background-color: white");
              }
          */
          

          However this way my delegate only appears with a grayish background (i want it to be white) and does not get the selected blueish color.

          Here is a picture visualizing what i mean:
          f8bb9f43-18cd-4b40-bb70-943fe7b29f9a-image.png

          My draw row statement looks like this now:

          void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
          {
             
              if (selectionModel()->isSelected(index)) {
              
              // Zeichnen Sie den Einzugsbereich (Indentation) mit Ihrer gewünschten Farbe
                      QRect indentRect = visualRect(index);
                      indentRect.setRight(options.rect.left()); 
                      painter->fillRect(indentRect, QColor(173, 216, 230));
              }
          
          
              
               QTreeView::drawRow(painter, options, index); // Rufen Sie die Basisimplementierung auf, um die Standardzeichnung durchzuführen
          }
          
          

          Note: i also tried leaving out:

                   indentRect.setRight(options.rect.left()); 
          

          but this did not work.

          1 Reply Last reply
          0
          • S StudentScripter

            So i created my QStyledItemDelegate and actually highlighting the delegate does work, but the identation space of my QTreeView stays white. I want the identationspace to get highlighted too.

            Here is how it looks like right now: febae6c7-5d1c-4ead-acc5-fb2bb0a8a9fa-image.png

            Ps: it would be even better if the identation space would be gone if there is no item grouped below, but still the whole entry should be highlighted blue.

            Here is my code for the delegate, please help me:
            .cpp:

            #include "ViewLayerItemDelegate.h"
            #include <QStyledItemDelegate>
            #include <QPainter>
            #include <QApplication>
            
            
            
            
            ViewLayerItemDelegate::ViewLayerItemDelegate(QObject *parent)
                : QStyledItemDelegate{parent}
            {
            
            }
            
            
            
            QWidget *ViewLayerItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
            {
                qDebug() << "Editor created";
                
                LineEditCheckBoxWidget *editor = new LineEditCheckBoxWidget(parent);
                if (option.state & QStyle::State_Selected) {
                    //editor->setStyleSheet("background-color: lightblue;");
                }
            
               // Verbinden Sie das textChanged() Signal des LineEdits mit Ihrem Slot
                connect(editor->lineEdit, &QLineEdit::textChanged, this, &ViewLayerItemDelegate::onLineEditTextChanged);
            
            
            
                return editor;
            }
            
            
            
            
            void ViewLayerItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
            {
            
                
                LineEditCheckBoxWidget *widget = static_cast<LineEditCheckBoxWidget *>(editor);
            
                // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten
                QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
                bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
            
                widget->lineEdit->setText(lineEditvalue);
                widget->checkBox->setChecked(checkBoxValue);
                
                
            
            
                widget->lineEdit->setFocus(Qt::MouseFocusReason); // Editor aktivieren
                widget->lineEdit->setStyleSheet("");
                widget->iconLabel->setAttribute(Qt::WA_TranslucentBackground);
                widget->setStyleSheet("background: white");
                    
            }
            
            
            
            
            void ViewLayerItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
            {
                
                
                LineEditCheckBoxWidget *widget = static_cast<LineEditCheckBoxWidget *>(editor);
            
                
            
                // Speichern Sie die Werte der SpinBox und CheckBox im Modell
                QString lineEditvalue = widget->lineEdit->text();
                bool checkBoxValue = widget->checkBox->isChecked();
            
                model->setData(index, lineEditvalue, Qt::EditRole);
                model->setData(index, checkBoxValue ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
                
                qDebug() << "Model data set";
            }
            
            
            
            
            void ViewLayerItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
            {
                editor->setGeometry(option.rect);
            }
            
            
            
            
            QSize ViewLayerItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
            {
                
                QSize size = QStyledItemDelegate::sizeHint(option, index);
                    size.setHeight(40); // Setzen Sie hier die gewünschte Höhe
                return size;
            }
            
            
            
            
            
            
            void ViewLayerItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
            {
                QStyleOptionViewItem opt = option;
                initStyleOption(&opt, index);
            
                LineEditCheckBoxWidget widget;
            
                // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten
                QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
                bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
            
                widget.lineEdit->setText(lineEditvalue);
                widget.checkBox->setChecked(checkBoxValue);
            
                // Laden Sie das Icon und setzen Sie es auf das QLabel
                QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
                QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
                widget.iconLabel->setPixmap(scaledPixmap);
            
               
            
                // Passen Sie das Aussehen des Widgets basierend auf der QStyleOptionViewItem an
                if (opt.state & QStyle::State_Selected) {
                
                    widget.setStyleSheet("background-color: lightblue;");
                    
                }else{
                qDebug() << "Test"; 
                widget.setStyleSheet("background-color: white");
                }
            
                widget.resize(option.rect.size()); // Stellen Sie sicher, dass die Größe des Widgets der Größe des Elements entspricht
            
                // Rendern Sie das Widget in den Painter
                QPixmap pixmap(widget.size());
                widget.render(&pixmap);
            
                // Zeichnen Sie das Pixmap mit dem QPainter
                painter->drawPixmap(option.rect.topLeft(), pixmap);
            }
            
            
            
            
            // Slot-Implementierung
            void ViewLayerItemDelegate::onLineEditTextChanged(const QString &text)
            {
                // Hier können Sie die gewünschte Aktion ausführen, wenn der Text im LineEdit bearbeitet wird
                qDebug() << "LineEdit text changed to:" << text;
            }
            
            
            
            
            
            
            
            
            
            void LineEditCheckBoxWidget::mousePressEvent(QMouseEvent *event)
            {
                qDebug() << "Test clicked";
            
                QWidget::mousePressEvent(event);
            }
            
            

            and here delegate.h:

            #ifndef VIEWLAYERITEMDELEGATE_H
            #define VIEWLAYERITEMDELEGATE_H
            
            #include <QStyledItemDelegate>
            #include <QModelIndex>
            #include <QObject>
            #include <QSize>
            #include <QLineEdit>
            #include <QStandardItemModel>
            #include <QCheckBox>
            #include <QFormLayout>
            #include <QLabel>
            #include <QPushButton>
            
            
            
            
            // Definieren Sie das benutzerdefinierte Widget
            class LineEditCheckBoxWidget : public QWidget {
                Q_OBJECT
            public:
                QLineEdit *lineEdit;
                QCheckBox *checkBox;
                QLabel *iconLabel;
            
            
                LineEditCheckBoxWidget(QWidget *parent = nullptr) : QWidget(parent) {
                    QHBoxLayout *layout = new QHBoxLayout(this);
                    layout->setContentsMargins(10,0,20,0);
                    layout->setSpacing(0);
                    lineEdit = new QLineEdit(this);
                    checkBox = new QCheckBox(this);
                    iconLabel = new QLabel(this);
            
            
                    // Laden Sie das Icon und setzen Sie es auf das QLabel
                    QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
                    QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
                    iconLabel->setPixmap(scaledPixmap);
            
            
            
                    layout->addWidget(iconLabel);
                    layout->addSpacing(10);
                    layout->addWidget(lineEdit);
                    layout->addStretch(1);
                    layout->addWidget(checkBox);
            
                    // Zugriff auf das QLineEdit-Widget und setzen Sie den Hintergrund transparent
                    lineEdit->setStyleSheet("background: transparent;");
                    lineEdit->setFrame(false);
                    lineEdit->setPlaceholderText("<Empty>");
            
                    checkBox->setStyleSheet("background: transparent");
                }
                
                // QWidget interface
            protected:
                void mousePressEvent(QMouseEvent *event) override;
                
            signals:
            
            };
            
            
            
            
            
            
            
            class ViewLayerItemDelegate : public QStyledItemDelegate
            {
                Q_OBJECT
            public:
                explicit ViewLayerItemDelegate(QObject *parent = nullptr);
                
                
                
                QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
                void setEditorData(QWidget *editor, const QModelIndex &index) const override;
                void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
                void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
                
                QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
                void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
                
                
                
            public slots:
                
                void onLineEditTextChanged(const QString &text);
            
            
            signals:
                
                
                
                
                
                
            
            };
               
            
            #endif // VIEWLAYERITEMDELEGATE_H
            
            

            Thanks for helping, really really appreciate that. <3

            qwasder85Q Offline
            qwasder85Q Offline
            qwasder85
            wrote on last edited by qwasder85
            #7

            @StudentScripter Have you tried a simple stylesheet such as this:

            QTreeView::item:selected
            {
                background-color: red;
            }
            
            QTreeView::branch:selected
            {
                background-color: red;
            }
            

            No need to handle the painting manually.

            S 1 Reply Last reply
            0
            • qwasder85Q qwasder85

              @StudentScripter Have you tried a simple stylesheet such as this:

              QTreeView::item:selected
              {
                  background-color: red;
              }
              
              QTreeView::branch:selected
              {
                  background-color: red;
              }
              

              No need to handle the painting manually.

              S Offline
              S Offline
              StudentScripter
              wrote on last edited by StudentScripter
              #8

              @qwasder85 Yes thank you, i tried it but you have to know that i have implemented a paint methode for my delegate in order to display the controls as pixmap, even when the editor is not open:

              delegate.cpp:

              void ViewLayerItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
              {
                  QStyleOptionViewItem opt = option;
                  initStyleOption(&opt, index);
              
                  LineEditCheckBoxWidget widget;
              
              
                  QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
                  bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
              
                  widget.lineEdit->setText(lineEditvalue);
                  widget.checkBox->setChecked(checkBoxValue);
              
              
                  QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
                  QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
                  widget.iconLabel->setPixmap(scaledPixmap);
              
                 
              
                  if (opt.state & QStyle::State_Selected) {
                  
                  widget.setStyleSheet("background-color: lightblue;");
                      
                  }else{
              
                  widget.setStyleSheet("background-color: white");
                  }
              
                  widget.resize(option.rect.size()); 
              
              
                  QPixmap pixmap(widget.size());
                  widget.render(&pixmap);
              
                  painter->drawPixmap(option.rect.topLeft(), pixmap);
              }
              
              

              implementing a stylesheet for branch highlighting in the treeview like this:

              QTreeView.cpp

              
              ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent)
                  : QTreeView{parent}, scene_durchgereicht(scene)
              {
              
               // Setzen Sie das Stylesheet für den ausgewählten Zweig hier
                  setStyleSheet("QTreeView::item:selected { background-color: yellow; }");
              }
              

              (i also tried branch, row .... isn't cutting it) always ends up looking like:
              5d4e95c2-c4fa-4f55-9f1f-a45a8b1bc58d-image.png

              vs. this with my delegate code: (so it looks like it should look like) but as @Chris-Kawa mentioned, thats not a good way to do it, so im looking for a better way instead of painting the highlight twice, once in my delegate and once in my QTreeView
              66ea05a2-eead-4a97-ab47-9926a3b3d181-image.png

              Chris KawaC 1 Reply Last reply
              0
              • S StudentScripter

                @qwasder85 Yes thank you, i tried it but you have to know that i have implemented a paint methode for my delegate in order to display the controls as pixmap, even when the editor is not open:

                delegate.cpp:

                void ViewLayerItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
                {
                    QStyleOptionViewItem opt = option;
                    initStyleOption(&opt, index);
                
                    LineEditCheckBoxWidget widget;
                
                
                    QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
                    bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
                
                    widget.lineEdit->setText(lineEditvalue);
                    widget.checkBox->setChecked(checkBoxValue);
                
                
                    QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
                    QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
                    widget.iconLabel->setPixmap(scaledPixmap);
                
                   
                
                    if (opt.state & QStyle::State_Selected) {
                    
                    widget.setStyleSheet("background-color: lightblue;");
                        
                    }else{
                
                    widget.setStyleSheet("background-color: white");
                    }
                
                    widget.resize(option.rect.size()); 
                
                
                    QPixmap pixmap(widget.size());
                    widget.render(&pixmap);
                
                    painter->drawPixmap(option.rect.topLeft(), pixmap);
                }
                
                

                implementing a stylesheet for branch highlighting in the treeview like this:

                QTreeView.cpp

                
                ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent)
                    : QTreeView{parent}, scene_durchgereicht(scene)
                {
                
                 // Setzen Sie das Stylesheet für den ausgewählten Zweig hier
                    setStyleSheet("QTreeView::item:selected { background-color: yellow; }");
                }
                

                (i also tried branch, row .... isn't cutting it) always ends up looking like:
                5d4e95c2-c4fa-4f55-9f1f-a45a8b1bc58d-image.png

                vs. this with my delegate code: (so it looks like it should look like) but as @Chris-Kawa mentioned, thats not a good way to do it, so im looking for a better way instead of painting the highlight twice, once in my delegate and once in my QTreeView
                66ea05a2-eead-4a97-ab47-9926a3b3d181-image.png

                Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #9

                @StudentScripter For painting the selection I simply meant this, without adjusting the area at all:

                if (selectionModel()->isSelected(index)) {
                   painter->fillRect(options.rect, QColor(173, 216, 230));
                }
                

                The widget (or the picture of it) in the item is displayed "above" the row, so it covers whatever the view painted for the row. If you'd like to go with the approach that only view paints selection then make sure that the widget (and the picture of it) has transparent background, so the underlying row is visible.

                S 1 Reply Last reply
                1
                • Chris KawaC Chris Kawa

                  @StudentScripter For painting the selection I simply meant this, without adjusting the area at all:

                  if (selectionModel()->isSelected(index)) {
                     painter->fillRect(options.rect, QColor(173, 216, 230));
                  }
                  

                  The widget (or the picture of it) in the item is displayed "above" the row, so it covers whatever the view painted for the row. If you'd like to go with the approach that only view paints selection then make sure that the widget (and the picture of it) has transparent background, so the underlying row is visible.

                  S Offline
                  S Offline
                  StudentScripter
                  wrote on last edited by
                  #10

                  @Chris-Kawa Yes thank you very much, i have done this now. Sadly and i don't know why, suddenly the intendation space isn't painted highlighted anymore:

                  69fd9d57-0953-423b-bd21-0bc3195f3162-image.png

                  void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
                  {
                     
                      if (selectionModel()->isSelected(index)) {
                      
                      // Zeichnen Sie den Einzugsbereich (Indentation) mit Ihrer gewünschten Farbe
                              QRect indentRect = visualRect(index);
                              painter->fillRect(indentRect, QColor(173, 216, 230)); // "lightblue" Hervorhebungsfarbe*/
                              
                         
                              
                          
                      }
                  
                      
                       QTreeView::drawRow(painter, options, index); // Rufen Sie die Basisimplementierung auf, um die Standardzeichnung durchzuführen
                  }
                  
                  

                  it only works when adding the stylesheet solution to the treeview constructor, but i guess thats not what you meant:
                  d18bde15-6933-492c-94db-c7d1549a60d2-image.png

                  
                  ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent)
                      : QTreeView{parent}, scene_durchgereicht(scene)
                  {
                  
                  // Setzen Sie das Stylesheet für den ausgewählten Zweig hier
                      setStyleSheet("QTreeView::item:selected { background-color: lightblue; }");
                  
                  Chris KawaC 1 Reply Last reply
                  0
                  • S StudentScripter

                    @Chris-Kawa Yes thank you very much, i have done this now. Sadly and i don't know why, suddenly the intendation space isn't painted highlighted anymore:

                    69fd9d57-0953-423b-bd21-0bc3195f3162-image.png

                    void ViewLayerList::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
                    {
                       
                        if (selectionModel()->isSelected(index)) {
                        
                        // Zeichnen Sie den Einzugsbereich (Indentation) mit Ihrer gewünschten Farbe
                                QRect indentRect = visualRect(index);
                                painter->fillRect(indentRect, QColor(173, 216, 230)); // "lightblue" Hervorhebungsfarbe*/
                                
                           
                                
                            
                        }
                    
                        
                         QTreeView::drawRow(painter, options, index); // Rufen Sie die Basisimplementierung auf, um die Standardzeichnung durchzuführen
                    }
                    
                    

                    it only works when adding the stylesheet solution to the treeview constructor, but i guess thats not what you meant:
                    d18bde15-6933-492c-94db-c7d1549a60d2-image.png

                    
                    ViewLayerList::ViewLayerList(CustomGraphicsScene *scene, QWidget *parent)
                        : QTreeView{parent}, scene_durchgereicht(scene)
                    {
                    
                    // Setzen Sie das Stylesheet für den ausgewählten Zweig hier
                        setStyleSheet("QTreeView::item:selected { background-color: lightblue; }");
                    
                    Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #11

                    @StudentScripter You're painting the wrong rectangle. Look at the code you posted and the one I did.

                    S 1 Reply Last reply
                    0
                    • Chris KawaC Chris Kawa

                      @StudentScripter You're painting the wrong rectangle. Look at the code you posted and the one I did.

                      S Offline
                      S Offline
                      StudentScripter
                      wrote on last edited by
                      #12

                      @Chris-Kawa Well, what a pitty, i indeed missed this. 😅 Thanks for your patience with me.

                      May can i bother you again with another question related to this widget:
                      I know about the setEditTriggers() but still when i set:

                      setEditTriggers(QAbstractItemView::AllEditTriggers);
                      

                      cc121d67-2642-4c81-99ea-903f2190f42d-image.png
                      Like it is now i have to doubleclick to create the editor and click a third time again to focus the line edit, thats pretty user unfriendly and wierd.

                      Instead i want to double click onto the position where my lineedit is to select and focus/write into it.
                      Also with the checkbox i would like to click on it and it should be ticked instantly on the first click. I guess i have to implement this logic somehow myself into QTreeView mousePressEvent, but i have no good idea on how to do that? Maybe with openpersitentEditor and than somehow set focus to the widget depending on what is under the clicked mouse position?

                      Also can't say it often enough thanks for your help and the help of the others. I really doubt i would have gotten this far without. :D Also have to admit this photoeditor clone is my first big project that i set myself, of course only with basic features, but i really want to tweak them to be useful in a real world scenario.

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #13

                        No, check the editorEvent function.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        S 2 Replies Last reply
                        0
                        • SGaistS SGaist

                          No, check the editorEvent function.

                          S Offline
                          S Offline
                          StudentScripter
                          wrote on last edited by
                          #14

                          @SGaist thanks that seems the right direction, however i cant get the mouse position to be into the checkbox. Visually it looks like i click into the check box but my debug says its not clicking into the checkbox. I tried mapping to global in order to align both positions but i had no luck with this:

                          
                          
                          bool ViewLayerItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
                          {
                              if(event->type() == QEvent::MouseButtonPress)
                              {
                                  QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
                                  
                                  QWidget *parentWidget = qobject_cast<QWidget*>(parent());
                                  if(parentWidget)
                                  {
                                      
                                      QWidget *editor = createEditor(parentWidget, option, index);
                                     
                                          LineEditCheckBoxWidget *widget = qobject_cast<LineEditCheckBoxWidget*>(editor);
                                          if(widget)
                                          {   
                                         
                                              
                                          QPoint mousePosition = widget->checkBox->mapFromGlobal(mouseEvent->globalPos());
                                          QRect checkboxGeometry = widget->checkBox->geometry();
                                          QRect globalCheckboxGeometry;
                                          globalCheckboxGeometry.setTopLeft(widget->checkBox->mapToGlobal(checkboxGeometry.topLeft()));
                                          globalCheckboxGeometry.setBottomRight(widget->checkBox->mapToGlobal(checkboxGeometry.bottomRight()));
                          
                          
                                             qDebug() << "Checkboxdata: " << globalCheckboxGeometry;
                          
                                             qDebug() << "MousePostion: " << mousePosition;
                          
                          
                                              /*
                                               //IGNORE: later i want to check here if the positon 
                                               //is the same in order to perform further actions
                                              bool checked = widget->checkBox->isChecked();
                                              widget->checkBox->setChecked(!checked);
                                              setModelData(editor, model, index);
                                              return true; 
                                              */
                                          }
                                  }
                          
                                
                             
                              }
                              
                              return QStyledItemDelegate::editorEvent(event, model, option, index);
                          }
                          
                          

                          I get for example:
                          Checkboxdata: QRect(1095,302 100x30)
                          MousePostion: QPoint(215,21)

                          1 Reply Last reply
                          0
                          • SGaistS SGaist

                            No, check the editorEvent function.

                            S Offline
                            S Offline
                            StudentScripter
                            wrote on last edited by
                            #15

                            @SGaist Bumping this up. Guess you are busy but may you have a second the next days or so to may answer my last question. Sorry for the interuption. :)

                            Chris KawaC 1 Reply Last reply
                            0
                            • S StudentScripter

                              @SGaist Bumping this up. Guess you are busy but may you have a second the next days or so to may answer my last question. Sorry for the interuption. :)

                              Chris KawaC Offline
                              Chris KawaC Offline
                              Chris Kawa
                              Lifetime Qt Champion
                              wrote on last edited by
                              #16

                              @StudentScripter There's multiple problems in your code.

                              First this is wrong: QWidget *parentWidget = qobject_cast<QWidget*>(parent());.
                              A delegate can be shared between multiple views and there's no requirement that any of those views was a parent of that delegate. There's also no requirement that the parent of the delegate is a QWidget or that the delegate even has any parent. In case of sharing delegate between views the parent might not even be the widget the event occurred in.
                              The proper way to retrieve the widget the event happened in is through option.widget parameter.

                              Next, you should not call createEditor. This is a callback method that the view calls when editing of an item is requested via view->edit(index). The way you have it you create a new widget every time an item is clicked. you never show or delete that widget, but you do give it a parent, so after 1000 clicks you have 1000 instances of that widget created, invisible and living until you the view is destroyed.

                              The event gives you press position in view's viewport coordinates. To convert it to item's coordinates you can get the item coords in the viewport and do the math e.g.

                              if(event->type() == QEvent::MouseButtonPress)
                              {
                                  QMouseEvent* mouseEvt = static_cast<QMouseEvent*>(event);
                                  
                                  if ( const QTreeView* view = qobject_cast<const QTreeView*>(option.widget))
                                  {
                                      const QRect itemRect = view->visualRect(index);
                                      QPointF itemPos = mouseEvt->position() - itemRect.topLeft(); // press position in item's coords
                              

                              You should not create and destroy a widget every time you want to paint or check a position in it. That's an enormous overhead that defeats the whole point of delegates.

                              Calculate where your checkbox is without instantiating a widget. For example you can assume it's always in a right aligned square of your item, so you can calculate its position from the item dimensions.

                              When painting the item you also shouldn't instantiate a widget and take a screenshot of it like you're doing now. Use style()->drawControl(...) to draw a picture of a checkbox or line edit without actually instantiating them. That's the idea of delegates - provide a lightweight proxy for the items and only instantiating an actual widget when editing of an item starts.

                              When painting an item don't load any resources e.g. QPixmap iconPixmap("://resource/quick.png"); in the paint event. That is reading from disk and can stall and make your app unresponsive if you have many items or slow disk access. Load the image once e.g. in the delegate's constructor and store it in a class member. Also if you're doing any transformation on it, like scaled(...) do it once on load and store and reuse the result. Keep in mind that the paining is called every time a user moves a mouse over an item, so it's potentially hundreds of events a second. Painting should be as speedy as possible.

                              Don't use stylesheets to draw a colored rectangle. It's like shooting a fly with a canon. Just use a QPainter and paint a rectangle.

                              S 3 Replies Last reply
                              3
                              • Chris KawaC Chris Kawa

                                @StudentScripter There's multiple problems in your code.

                                First this is wrong: QWidget *parentWidget = qobject_cast<QWidget*>(parent());.
                                A delegate can be shared between multiple views and there's no requirement that any of those views was a parent of that delegate. There's also no requirement that the parent of the delegate is a QWidget or that the delegate even has any parent. In case of sharing delegate between views the parent might not even be the widget the event occurred in.
                                The proper way to retrieve the widget the event happened in is through option.widget parameter.

                                Next, you should not call createEditor. This is a callback method that the view calls when editing of an item is requested via view->edit(index). The way you have it you create a new widget every time an item is clicked. you never show or delete that widget, but you do give it a parent, so after 1000 clicks you have 1000 instances of that widget created, invisible and living until you the view is destroyed.

                                The event gives you press position in view's viewport coordinates. To convert it to item's coordinates you can get the item coords in the viewport and do the math e.g.

                                if(event->type() == QEvent::MouseButtonPress)
                                {
                                    QMouseEvent* mouseEvt = static_cast<QMouseEvent*>(event);
                                    
                                    if ( const QTreeView* view = qobject_cast<const QTreeView*>(option.widget))
                                    {
                                        const QRect itemRect = view->visualRect(index);
                                        QPointF itemPos = mouseEvt->position() - itemRect.topLeft(); // press position in item's coords
                                

                                You should not create and destroy a widget every time you want to paint or check a position in it. That's an enormous overhead that defeats the whole point of delegates.

                                Calculate where your checkbox is without instantiating a widget. For example you can assume it's always in a right aligned square of your item, so you can calculate its position from the item dimensions.

                                When painting the item you also shouldn't instantiate a widget and take a screenshot of it like you're doing now. Use style()->drawControl(...) to draw a picture of a checkbox or line edit without actually instantiating them. That's the idea of delegates - provide a lightweight proxy for the items and only instantiating an actual widget when editing of an item starts.

                                When painting an item don't load any resources e.g. QPixmap iconPixmap("://resource/quick.png"); in the paint event. That is reading from disk and can stall and make your app unresponsive if you have many items or slow disk access. Load the image once e.g. in the delegate's constructor and store it in a class member. Also if you're doing any transformation on it, like scaled(...) do it once on load and store and reuse the result. Keep in mind that the paining is called every time a user moves a mouse over an item, so it's potentially hundreds of events a second. Painting should be as speedy as possible.

                                Don't use stylesheets to draw a colored rectangle. It's like shooting a fly with a canon. Just use a QPainter and paint a rectangle.

                                S Offline
                                S Offline
                                StudentScripter
                                wrote on last edited by StudentScripter
                                #17
                                This post is deleted!
                                1 Reply Last reply
                                0
                                • Chris KawaC Chris Kawa

                                  @StudentScripter There's multiple problems in your code.

                                  First this is wrong: QWidget *parentWidget = qobject_cast<QWidget*>(parent());.
                                  A delegate can be shared between multiple views and there's no requirement that any of those views was a parent of that delegate. There's also no requirement that the parent of the delegate is a QWidget or that the delegate even has any parent. In case of sharing delegate between views the parent might not even be the widget the event occurred in.
                                  The proper way to retrieve the widget the event happened in is through option.widget parameter.

                                  Next, you should not call createEditor. This is a callback method that the view calls when editing of an item is requested via view->edit(index). The way you have it you create a new widget every time an item is clicked. you never show or delete that widget, but you do give it a parent, so after 1000 clicks you have 1000 instances of that widget created, invisible and living until you the view is destroyed.

                                  The event gives you press position in view's viewport coordinates. To convert it to item's coordinates you can get the item coords in the viewport and do the math e.g.

                                  if(event->type() == QEvent::MouseButtonPress)
                                  {
                                      QMouseEvent* mouseEvt = static_cast<QMouseEvent*>(event);
                                      
                                      if ( const QTreeView* view = qobject_cast<const QTreeView*>(option.widget))
                                      {
                                          const QRect itemRect = view->visualRect(index);
                                          QPointF itemPos = mouseEvt->position() - itemRect.topLeft(); // press position in item's coords
                                  

                                  You should not create and destroy a widget every time you want to paint or check a position in it. That's an enormous overhead that defeats the whole point of delegates.

                                  Calculate where your checkbox is without instantiating a widget. For example you can assume it's always in a right aligned square of your item, so you can calculate its position from the item dimensions.

                                  When painting the item you also shouldn't instantiate a widget and take a screenshot of it like you're doing now. Use style()->drawControl(...) to draw a picture of a checkbox or line edit without actually instantiating them. That's the idea of delegates - provide a lightweight proxy for the items and only instantiating an actual widget when editing of an item starts.

                                  When painting an item don't load any resources e.g. QPixmap iconPixmap("://resource/quick.png"); in the paint event. That is reading from disk and can stall and make your app unresponsive if you have many items or slow disk access. Load the image once e.g. in the delegate's constructor and store it in a class member. Also if you're doing any transformation on it, like scaled(...) do it once on load and store and reuse the result. Keep in mind that the paining is called every time a user moves a mouse over an item, so it's potentially hundreds of events a second. Painting should be as speedy as possible.

                                  Don't use stylesheets to draw a colored rectangle. It's like shooting a fly with a canon. Just use a QPainter and paint a rectangle.

                                  S Offline
                                  S Offline
                                  StudentScripter
                                  wrote on last edited by
                                  #18

                                  @Chris-Kawa thank you very much. That definitely helped a lot. :)

                                  I have done the manual positioning now, so all delegates line up with the actual widget. :)

                                  
                                  void ViewLayerItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
                                  {
                                      
                                      
                                      QStyleOptionViewItem opt = option;
                                      initStyleOption(&opt, index);
                                  
                                  
                                      // Überprüfen Sie, ob der aktuelle Index bearbeitet wird
                                          if (index == currentlyEditedIndex) {
                                             
                                              return;
                                          }
                                  
                                  
                                  
                                      // Setzen Sie die Werte der SpinBox und CheckBox basierend auf den Modellwerten
                                      QString lineEditvalue = index.model()->data(index, Qt::EditRole).toString();
                                      bool checkBoxValue = index.model()->data(index, Qt::CheckStateRole).toBool();
                                  
                                      // Laden Sie das Icon und skalieren Sie es
                                      QPixmap iconPixmap("://resource/quick.png"); // Ersetzen Sie dies durch den Pfad zu Ihrer Icon-Datei
                                      QPixmap scaledPixmap = iconPixmap.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
                                      
                                      // Berechnen Sie die Position für das Icon
                                      int centerY = option.rect.top() + option.rect.height() / 2;
                                      int iconY = centerY - scaledPixmap.height() / 2;
                                      QPoint iconPos = QPoint(option.rect.left() + 10, iconY);
                                      
                                      // Zeichnen Sie das Pixmap mit dem QPainter
                                      painter->drawPixmap(iconPos, scaledPixmap);
                                  
                                  
                                      // Berechnen Sie die Position und Größe für das LineEdit
                                      QRect lineEditRect = option.rect;
                                      lineEditRect.setLeft(iconPos.x() + scaledPixmap.width() + 10); // Adjust as needed
                                      lineEditRect.setRight(option.rect.right() - 10); // Adjust as needed
                                  
                                      // Erstellen Sie ein QStyleOptionFrame für das LineEdit
                                      QStyleOptionFrame lineEditOption;
                                      lineEditOption.lineWidth = 1; // Setzen Sie die Liniendicke auf 1
                                      lineEditOption.rect = lineEditRect;
                                  
                                      // Zeichnen Sie das LineEdit
                                      QApplication::style()->drawControl(QStyle::CE_ShapedFrame, &lineEditOption, painter);
                                  
                                      // Zeichnen Sie den Text des LineEdits
                                      painter->drawText(lineEditOption.rect.adjusted(2,0,0,0), Qt::AlignLeft | Qt::AlignVCenter, lineEditvalue);
                                  
                                      // Berechnen Sie die Position und Größe für die CheckBox
                                      QRect checkBoxRect = option.rect;
                                      checkBoxRect.setLeft(lineEditRect.right() - 22); // Adjust as needed
                                      checkBoxRect.setRight(option.rect.right() - 10); // Adjust as needed
                                  
                                      // Erstellen Sie ein QStyleOptionButton für die CheckBox
                                      QStyleOptionButton checkBoxOption;
                                      checkBoxOption.state = checkBoxValue ? QStyle::State_On : QStyle::State_Off;
                                      checkBoxOption.rect = checkBoxRect;
                                  
                                      // Zeichnen Sie die CheckBox
                                      QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxOption, painter);
                                  }
                                  
                                  1 Reply Last reply
                                  0
                                  • Chris KawaC Chris Kawa

                                    @StudentScripter There's multiple problems in your code.

                                    First this is wrong: QWidget *parentWidget = qobject_cast<QWidget*>(parent());.
                                    A delegate can be shared between multiple views and there's no requirement that any of those views was a parent of that delegate. There's also no requirement that the parent of the delegate is a QWidget or that the delegate even has any parent. In case of sharing delegate between views the parent might not even be the widget the event occurred in.
                                    The proper way to retrieve the widget the event happened in is through option.widget parameter.

                                    Next, you should not call createEditor. This is a callback method that the view calls when editing of an item is requested via view->edit(index). The way you have it you create a new widget every time an item is clicked. you never show or delete that widget, but you do give it a parent, so after 1000 clicks you have 1000 instances of that widget created, invisible and living until you the view is destroyed.

                                    The event gives you press position in view's viewport coordinates. To convert it to item's coordinates you can get the item coords in the viewport and do the math e.g.

                                    if(event->type() == QEvent::MouseButtonPress)
                                    {
                                        QMouseEvent* mouseEvt = static_cast<QMouseEvent*>(event);
                                        
                                        if ( const QTreeView* view = qobject_cast<const QTreeView*>(option.widget))
                                        {
                                            const QRect itemRect = view->visualRect(index);
                                            QPointF itemPos = mouseEvt->position() - itemRect.topLeft(); // press position in item's coords
                                    

                                    You should not create and destroy a widget every time you want to paint or check a position in it. That's an enormous overhead that defeats the whole point of delegates.

                                    Calculate where your checkbox is without instantiating a widget. For example you can assume it's always in a right aligned square of your item, so you can calculate its position from the item dimensions.

                                    When painting the item you also shouldn't instantiate a widget and take a screenshot of it like you're doing now. Use style()->drawControl(...) to draw a picture of a checkbox or line edit without actually instantiating them. That's the idea of delegates - provide a lightweight proxy for the items and only instantiating an actual widget when editing of an item starts.

                                    When painting an item don't load any resources e.g. QPixmap iconPixmap("://resource/quick.png"); in the paint event. That is reading from disk and can stall and make your app unresponsive if you have many items or slow disk access. Load the image once e.g. in the delegate's constructor and store it in a class member. Also if you're doing any transformation on it, like scaled(...) do it once on load and store and reuse the result. Keep in mind that the paining is called every time a user moves a mouse over an item, so it's potentially hundreds of events a second. Painting should be as speedy as possible.

                                    Don't use stylesheets to draw a colored rectangle. It's like shooting a fly with a canon. Just use a QPainter and paint a rectangle.

                                    S Offline
                                    S Offline
                                    StudentScripter
                                    wrote on last edited by StudentScripter
                                    #19
                                    This post is deleted!
                                    1 Reply Last reply
                                    0
                                    • S StudentScripter has marked this topic as solved on

                                    • Login

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • Users
                                    • Groups
                                    • Search
                                    • Get Qt Extensions
                                    • Unsolved